1

I'm trying to do the following thing:

#include <stdio.h>

typedef unsigned char Set[128];

Set A;  //Global variable

void main()
{
    A[0] = 1;
    A[1] = 2;
    A[2] = 3;
    printf("%x, %x, %x\n", A, &A, &A[0]);
    printf("%u, %u, %u\n", A[0], A[1], A[2]);
    Set *p;
    p = A;  //Same result with:  p = &A;
    printf("%x, %x, %x\n", p, &p, &p[0]);
    printf("%u, %u, %u\n", p[0], p[1], p[2]);
}

The first and third prints are fine - I get to see the addresses of the two variables, and for 'p' the address it points on. I want 'p' to point on 'A' so I'll be able to access to the values in the array of 'A' through 'p', but it doesn't work - the values at the fourth print are not as the second, it's not printing the values of the array. how can I create a pointer to 'Set' variable type?

2
  • Why did you create a typedef that complicated your example ? All your printf call are undefined behavior. Commented Dec 29, 2017 at 14:17
  • p = A is invalid. Assuming a high enough warning level the compiler would have mentioned it to you. Take the compiler's warning(s) serious. Commented Dec 29, 2017 at 14:23

3 Answers 3

2

You're using many wrong / mismatched format specifiers for the supplied argument types. This causes undefined behavior.

Remember, for a pointer type, you must use %p format specifier, and in case the pointer is not a pointer to a char type, you must cast the argument to void *.


Regarding the above statement for the requirement to cast, refer chapter §6.2.5/P28,

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. [....]

and footnote 48,

The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.


That being said, always pay attention to the types!!

In your code,

  • A is of type unsigned char [128] (array),
  • and p is of type unsigned char (*) [128].

Thus, p = A; is not a valid statement, as the types are not compatible. You must take the address of A to make the statement valid, something like

 p = &A;  // now the types are compatible
Sign up to request clarification or add additional context in comments.

3 Comments

@alk no, I had something which backs me up, actually... :)
@alk ah, got it. §6.2.5/P28.. "A pointer to void shall have the same representation and alignment requirements as a pointer to a character type."
Hello, again, it's me mario... ok. So I come up with new/old info stackoverflow.com/a/24304460/7076153 (read the end of the answer at the "Official interpretations" part), seem that send char * without cast to void * to printf() with %p is not strictly conforming. Because the footnote is misleading, it's just a recommandation.
1

Well that's because pointer type of p is different that type of a. Here when you try to use p[1] you are basically trying to access some memory which you don't have access to. (You have undefined behavior when you access p[1] etc). And also due to mismatched type you will also run into undefined behavior in printf itself.

Rather you can get what you want by (Now you will get desired array elements).

printf("%u, %u, %u\n", (*p)[0], (*p)[1], (*p)[2]);

Also to type ponters use %p format specifier. (Casting it to void*).

printf("%p, %p, %p\n", (void*)A, (void*)&A, (void*)&A[0]);

How to compile code?

Also try to compiler your code with all warnings enabled. gcc -Wall -Werror progname.c.

Compiler complained!

Also p=A compiler complained about it. Because you are assigning unsigned char* to unsigned char(*)[128].

 error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
     p = A;  //Same result with:  p = &A;
       ^

And

error: format ‘%x’ expects argument of type ‘unsigned int’, but argument 4 has type ‘unsigned char (*)[128]’ [-Werror=format=]
     printf("%x, %x, %x\n", p, &p, &p[0]);
                      ^

How to make these warnings go away?

p=&A;

This will do the correct assignment. And use the correct format specifiers as mentioned in answer.

How did the unsigned char* appear?

Well array decayed into pointer in this case - and it decayed into pointer to the first element. The type of the first element is unsigned char - a pointer to it would be unsigned char*. That's how it came into ...

Comments

1

p is pointer to type unsigned char [128], that means it is of type unsigned char (*)[128] while the type of A, after decay, is unsigned char *. Both are of incompatible type. You need

p = &A; 

and

printf("%p, %p, %p\n", (void *)A, (void *)&A, (void *)&A[0]);
printf("%u, %u, %u\n", A[0], A[1], A[2]);
Set *p;
p = &A; // Assign address of A which is of type unsigned char (*)[128]
printf("%p, %p, %p\n", (void *)p[0], (void *)p, (void *)&p[0]);
printf("%u, %u, %u\n", p[0][0], p[0][1], p[0][2]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.