Hi David,

On Fri, Jan 09, 2026 at 04:10:56PM +0100, David Brown wrote:
> On 09/01/2026 13:07, Alejandro Colomar via Gcc wrote:
> >     #define strnulB(s)        \
> >     ({                        \
> >             auto  s_ = s;     \
> >             s_ + strlen(s_);  \
> >     })
> > 
> > The problem with strnulB() is that it has a local variable 's_'.  This
> > means I can't pass an argument called s_.  That is, the following call
> > doesn't work:
> > 
> >     strnulB(s_);
> 
> That is always the risk of macros.  Usually people just pick parameter names
> and local variable names that are very unlikely to collide.  If you have
> -Winit-self (or -Werror=init-self) then collisions will be detected (as
> "auto s_ = s_;_" now gives a warning or error).

Yup, I have that enabled, and indeed is triggering.

> You can also use __LINE__ to generate unique symbols :
> 
> #define strnulX(s) ({ \
>     auto s__ ## __LINE__ = (s); \
>     s__ ## __LINE__ + strlen(s__ ## __LINE__ ); \
>     })

This doesn't solve it, because it is called from another macro, which
has the same __LINE__ value.

> But here you can probably just use a static inline function.  It is, IME,
> always better to use a static inline function than a function-like macro
> when possible:
> 
> static inline char * strnulY(char * s) {
>     return s + strlen(s);
> }

I can't use this.  I want something that preserves 'const', like the
C23 APIs using QChar.

I could in fact do both a function and a macro, plus all the magic for
doing QChar, but that's too much complexity, and would be better solved
with 'auto' in inline functions.


Have a lovely day!
Alex

> 
> 
> <https://godbolt.org/z/oGvcfbh14>
> 
> 
> > 
> > Is there a way to implement something like this?:
> > 
> >     #define strnulC(s)                           \
> >     ({                                           \
> >             static_assert(!has_side_effects(s)); \
> >             s + strlen(s);                       \
> >     })
> > 
> > If there's no way, it would be interesting to add compound literals of
> > function type to achieve this:
> > 
> >     #define strnulD(...)                                          \
> >     ((static inline auto                                          \
> >       (auto s))                                                   \
> >     {                                                             \
> >             return s + strlen(s);                                 \
> >     }(__VA_ARGS__))
> > 
> > Which guarantees that the argument is evaluated once.
> > 
> 
> Do you need your macro here to work with different types?  I'm not sure how
> that could make sense, since "strlen" is not generic and always treats its
> parameter as a char*.
> 
> If you do need something that can work with different types and you want to
> use functions to avoid possible issues with macro parameters, you can use
> _Generic :
> 
> #define strnulX(s) _Generic((s), \
>               char * : strnulX_char(s), \
>               char16_t * strnulX_char16(s), \
>               char32_t * strnulX_char32(s)
>       )(s)
> 
> Then define functions strnulX_char, strnulX_char16, and strnulX_char32 as
> separate functions.  (_Generic does not evaluate its argument, so
> side-effects don't matter to it.)
> 
> 

-- 
<https://www.alejandro-colomar.es>

Attachment: signature.asc
Description: PGP signature

Reply via email to