With the following code:
char randnum[KEYSIZE 1];
char temp[3];
char buff[KEYSIZE*2 1] = {0};
for (j = 0; i < KEYSIZE; i ) {
randnum[i] = rand()%256;
snprintf(temp, 3, "%.2x", (unsigned char)randnum[i]);
strcat(buff, &temp);
}
I'm getting incompatible pointer types passing 'char (*)[3]' to parameter of type 'const char *
at &temp
. This is fixed by using temp
instead.
I'm trying to understand the error message. I understand const char *
to be a pointer but I'm not sure what char (*)[3]
is referring to; specifically the (*)
. From what I can infer from the fix, I assume this to be a pointer to a pointer (EDIT: pointer). Is this correct?
CodePudding user response:
&temp
is the address of the whole array. The array is of type char [3]
, so the type of the address (pointer) is a pointer to that array, which is expressed as char (*) [3]
, read it as "pointer to an array of 3 char
s".
I assume this to be a pointer to a pointer.
No, it's pointer to an array.
CodePudding user response:
&temp
is a pointer to the array itself, and it does indeed have the type char (*)[3]
(it's a pointer to an array of three char
elements).
You should pass a pointer to the first element of the string, i.e. &temp[0]
, which is what plain temp
decay to.
So:
strcat(buff, temp);
CodePudding user response:
The function strcat
is declared the following way
char *strcat(char * restrict s1, const char * restrict s2);
As you can see the both its parameters expect expressions of the type char *
or const char *
.
In this call of the function
strcat(buff, &temp);
The first argument expression is indeed has the type char *
due to the implicit conversion of the array designator buff
declared like
char buff[KEYSIZE*2 1] = {0};
to a pointer to its first element.
While the second argument expression has the type char ( * )[3]
because you used the address of operator &
for the array temp
&temp
You need also to use as the argument the array designator temp
. In this case it will be implicitly converted to a pointer to its first element the similar way as with the array buff
.
strcat(buff, temp);
Pay attention to that initially the array random
should be declared as having the element type unsigned char
.
unsigned char randnum[KEYSIZE 1];
Moreover as the array is not designed to contain a string then it may be declared also like
unsigned char randnum[KEYSIZE];
char randnum[KEYSIZE 1];
CodePudding user response:
Arrays decay to pointers.
char temp[3];
temp
decays to pointer to char (char *
) referring the first element of the array&temp
decays to pointer to array of 3 characters (char (*)[3]
) referring beginning of the array&temp[n]
decays to pointer to char (char *
) referring the n-th element of the array
CodePudding user response:
The strcat
function is declared as (C17 7.24.3.1):
char *strcat(char * restrict s1,
const char * restrict s2);
Where the important part for the sake of this discussion is that the function expects char*
for both parameters. Though we can note that a char*
can be assigned to a const char*
, but not the other way around.
If we look at the correct use, strcat(buff, temp);
, then both buff
and temp
in that expression are arrays. But in most cases when an array is used in an expression, it "decays" into a pointer to it's first element, it becomes a char*
in this case.
Formally this "decay" is defined as (C17 6.3.2.1):
Except when it is the operand of the
sizeof
operator, or the unary&
operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.
However when you type &temp
, you stumble upon one of the above mentioned exceptions to this "array decay" rule, namely when used with the unary &
.
So instead of a char*
we end up with "address of a char [3]
". Which has to be expressed with a special pointer type used when pointing at arrays, char (*)[3]
, known as "pointer to array" or "array pointer".
C has pretty strict rules regarding implicit pointer conversions - it will not accept that a char(*)[3]
is passed to a parameter expected to be const char*
- they are incompatible pointer types - it is not a valid form of assignment.
When you know all of this, the compiler error is actually quite self-explanatory.
CodePudding user response:
char (*)[3]
is a pointer to an array of size 3.
temp
in its most "natural" form is of type char[3]
. However, because temp
also points to the first element of the array (which is a char
), it is allowed to "decay" into a char*
.
When you take &temp
, that gives the address of the temp
variable, not an address is located in the array. Again, in its most "natural" form, &temp
is of type char (*)[3]
because it is a pointer to a char[3]
. However, note that it is no longer an array type (rather a pointer-to-array), so it is not allowed to decay to char**
.
strcat(buff, temp);
fixes this because strcat
wants a char*
, not a char (*)[3]
.