Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

snprintf error. argument to sizeof is the same as destination

Tags:

c

gcc

printf

gcc 4.8 give me an error when I build

#include <string.h>
#include <stdio.h>

static inline void toto(char str[3])
{
    snprintf(str, sizeof(str), "XX"); 
}

int main(){
    char str[3]; 
    toto(str);
    return 0;
}

Here is the gcc error

error: argument to ‘sizeof’ in ‘snprintf’ call is the same expression as the destination; did you mean to provide an explicit length?

Note: I m using -Wall -Werror flags which convert warning to error.

There is something similar here In a comment, someone answered this

"For fixed length buffers, I usually use strncpy(dest, src, sizeof(dest)); dest[sizeof(dest)-1] = '\0'; That guarantees NULL termination and is just less hassle than snprintf not to mention that a lot of people use snprintf(dest, sizeof(dest), src); instead and are very surprised when their programs crash arbitrarily."

But this is wrong: gcc 4.8 say

"error: argument to ‘sizeof’ in ‘strncpy’ call is the same expression as the destination; did you mean to provide an explicit length? [-Werror=sizeof-pointer-memaccess]"

in gcc 4.8 documentation, they are talking about this issue: they say:

The behavior of -Wall has changed and now includes the new warning flag -Wsizeof-pointer-memaccess. This may result in new warnings in code that compiled cleanly with previous versions of GCC.

For example,

include string.h

struct A { };

int main(void) 
{
    A obj;
    A* p1 = &obj;
    A p2[10];

    memset(p1, 0, sizeof(p1)); // error
    memset(p1, 0, sizeof(*p1)); // ok, dereferenced
    memset(p2, 0, sizeof(p2)); // ok, array
    return 0;
}

Gives the following diagnostic: warning: argument to ‘sizeof’ in ‘void memset(void*, int, size_t)’ call is the same expression as the destination; did you mean to dereference it? [-Wsizeof-pointer-memaccess] memset(p1, 0, sizeof(p1)); // error ^ Although these warnings will not result in compilation failure, often -Wall is used in conjunction with -Werror and as a result, new warnings are turned into new errors. To fix, either re-write to use memcpy or dereference the last argument in the offending memset call.*

Well, in their example, it's obvious the code was wrong, but in my case, with snprintf/strncpy, I dont see why, and I think it's a false positif error of gcc. Right ?

thanks for your help

like image 496
ramone Avatar asked Oct 05 '13 20:10

ramone


1 Answers

An array decays into a pointer to the first element when you passed to a function. So what you have in

static inline void toto(char str[3]) {..}

is not an array but a pointer.

Hence, gcc rightly warns.

Whether you specify the size in the function parameter or not doesn't matter as:

static inline void toto(char str[3])

and

static inline void toto(char str[])

and

static inline void toto(char *str)

are all equivalent.

Read here on this: what is array decaying?

like image 67
P.P Avatar answered Sep 22 '22 04:09

P.P