unusual output of the hexadecimal number - c

#include<stdio.h>
int main()
{
int a = 0xabcdef;
char *b = &a;
printf("%x",*b);
return 0;
}
above code gives output as ffffffef. What is the reason of this output?

Firstly, variable b is declared with type char *. You are trying to initialize it with value &a of type int *. This is illegal. The code is not valid C. The behavior is undefined.
Secondly, if your compiler managed to let this initialization slip through, then it probably performed an implicit conversion of the int * value to char * type. This makes pointer b to point to just one byte of variable a. The value of that single byte is what you see through *b. Which byte that is (in terms of the original value of a) is implementation-defined. E.g. you will typically you get a lower-order byte (0xEF) or a higher-order byte (0xAB).
Thirdly, it is implementation-defined whether type char is signed or unsigned. That means that the value of *b might be signed or unsigned, depending on your implementation. When you pass a char value *b to a variadic function printf, that char value is automatically converted to int type. The result of that conversion will generally depend on the signedness of type char. If your b points to the 0xEF byte, char is signed and int is 32-bit wide and uses 2's-complement, then the result, in hex terms, will look as 0xFFFFFFEF (which is a negative value).
Fourthly, %x format specifier requires an unsigned int argument, but instead you are passing an int argument with potentially negative value. The behavior is undefined.
In other words, your program is just a big pile of undefined and implementation-defined behavior. There's not much point in trying to explain why you got that specific output.

The pointer *b is a char type pointer and it's pointing to a int type variable. That's the reason of wrong output. Declare the pointer variable *b as int type.
int a = 0xabcdef;
int *b = &a;
printf("%x",*b);

Related

What does it mean that void* has the same representation and memory alignment as char*?

I've been reading some articles about void* type pointers and found this requirement from the Standard.
6.2.5.27:
A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.39) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements.
I see that the Standard does not guarantee all pointer types have the same length, so the bottom line here is that a void* pointer has the same length and alignment rules as char*, right?
What I don't get is the footnote 39), which says
The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.
My questions are:
What does it mean by "interchangeability"? Does it say the argument and the return values of a function void* Func(void*) can both be char*?
If so, is it an implicit conversion made by the compiler?
And what is it about the members of unions? I really don't get a grasp of the meaning of this. Can anyone give me a simple example?
In C any data pointer can be passed to a function that expects a void * and a void * can be stored to any pointer type. There is an implicit conversion between void * and other pointer types. But this does not mean that this conversion is harmless. On some architectures where void * and int * have a different representation, converting from int * to void * and then back to int * is specified as producing the same pointer value, but the converse does not hold: converting a void * to int * and back to void * may produce a different value, especially if the void * was not obtained by converting an int *.
Interchangeability means that this implicit conversion does not change the representation of the pointer. the conversion can be operated both ways successfully: converting a character pointer to void * and back produces the same pointer and vice versa.
Here is an example:
#include <assert.h>
#include <stdio.h>
#include <string.h>
int main() {
char *s = "abc";
char *s1;
void *p;
void *p1;
assert(sizeof(p) == sizeof(s));
memcpy(&p, &s, sizeof(p));
p1 = s;
assert(p == p1);
memcpy(&s1, &p1, sizeof(s1));
assert(s == s1);
return 0;
}
Note however that this does not imply that !memcmp(&p1, &s, sizeof(p1)) because pointers could have padding bits. Neither can you violate the strict aliasing rule by casting through a void *:
float f = 1.0; unsigned int i = *(int *)(void *)&f; incorrect.
float f = 1.0; unsigned int i; memcpy(&i, &f, sizeof(i)); correct if sizeof(int) == sizeof(float) but may produce a trap value.
What does it mean by "interchangeability"? Does it say the argument and the return values of a function void* Func(void*) can both be char*?
Yes, that is what it says, but it is non-normative text that conflicts with the normative text of the standard. Let’s discuss question 2 and then come back to this.
If so, is it an implicit conversion made by the compiler?
No, not in the situations intended to be addressed by this note.
If there is a visible declaration of void *Func(void *);, and you execute:
char *p = something;
char *q = Func(p);
then the argument p is converted void * and the returned value is converted to char *. But these conversions occur as part of the normal operations of function calls and assignments; they have nothing to do with the types having the same representation or being interchangeable. For example, if you executed code like the above but with int * instead of char *, the conversions would occur between int * and void * even if they do not have the same representations and are not interchangeable. The argument conversion is made because the compiler knows the parameter type of Func, so it performs the conversion as required by the rules for function calls, and the assignment conversion is made because the compiler knows the type of the destination of the assignment, so it performs the conversion as required by the rules for assignment.
However, suppose we have this code:
char *Func(char *);
char *p = something;
char *q = Func(p);
but Func is in fact defined in its library source code as void *Func(void *);. Then the rule in C 2018 6.2.5 281 applies. In the calling code, the compiler is told the parameter and the return type are char *, so no conversion is performed in either case. When passing the char * argument, the compiler passes exactly the bytes that represent a char *. In the receiving function, the code expects a void *. Since the bytes representing a char * are exactly the same as the bytes representing a void *, with the same meaning in regard to the represented address, this works: The function receives the bytes it expects to receive, with the intended meaning. Similarly, when the function returns the bytes for a void * and the calling code interprets those bytes as a char *, it works because the bytes are the same, with the same meaning.
Getting back to question 1, this example where Func is called using the type char *Func(char *) but is defined using the type void *Func(void *) violates the normative part of the C standard. C 2018 6.5.2.2 6 says:
If the function is defined with a type that includes a prototype, and… the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined.
char * is not compatible with void *, so the behavior is not defined by this rule. However, if the calling code is in one translation unit and the called code is in another translation unit, and no information about the calling code or the called function (notably no type information) is passed between translation units except for linking the name to the function, then it is impossible for the C implementation to distinguish our example code from code in which the function is called using a type compatible with its definition. In particular, the fact that char * has the same representation as void * means that the result of compiling the calling code must be identical whether it uses char *Func(char *) or void *Func(void *) (given the caveat that no type information ais passed between translation units), and it means that the result of compiling the function definition must be identical whether it is defined using char * or void *. In other words, a rule of the C standard says the behavior is not defined, but it is logically impossible in this situation for the compiler to compile the example code differently from the code with defined behavior.
I conjecture that this note in the standard may have been the result of the committee, or at least one or more members of it, wanting to say that, at least in some senses, char * could be used in place of void * and vice-versa, but that the committee did not have the time or motivation or other opportunity to draft formal language for this and make it a normative part of the standard, so it settled for making it a note.
And what is it about the members of unions? I really don't get a grasp of the meaning of this. Can anyone give me a simple example?
Consider this union:
union foo
{
void *v;
char *c;
float *f;
} u;
When we write into one union member, as with u.v = &a;, and read from another union member, as with char *p = u.c;, the bytes in the union are reinterpreted in the new type (C 2018 6.5.2.3 3 and note 99). Since void * and char * have the same representation, this reinterpretation must produce the same value. Thus, we are guaranteed that:
char a;
u.v = &a;
printf("%d\n", u.c == &a);
prints “1”. On the other hand, we are not guaranteed that for this code:
float f;
u.v = &f;
printf("%d\n", u.f == &f);
In this code, when &f is converted to void *, a void * might have a different representation from a float *, so the bytes representing &f may be different from the bytes representing (void *) &f. The latter are the bytes stored in u.v. When those bytes are read as u.f and reinterpreted as a float *, they might represent a different value, so the comparison might not evaluate as true.
Footnote
1 The question cites “6.2.5.27,” but the quoted passage is found in clause 6.2.5, paragraph 28, of the official 2018 C standard. The note cited as note 39 is found as note 49.
A pointer is just an address in the memory. You can think the memory is continuous region of a byte, which is very large (e.g. on a 32 bit process it will be 4 GB but usually the process is not able to use the whole depend on the system).
That mean the value of a pointer is actually an integer represent the zero-based index of a byte in the memory (e.g. pointer with value 0 refer to the first byte in the memory but in really you will not be able to de-reference this address due to it is a null pointer).
When you de-reference a pointer what it does is reading/writing to that address. The size to read/write is depend on the type of pointer. If a pointer is int and its size on that system is 32 bits, which is 4 bytes; it will read/write 4 bytes starting at that address. What alignment means is how the value stored in the memory. Let say if the value stored in memory need to be 16-bytes alignment that means its starting address must be multiply with 16.
What I explain here is just a high-level of the pointer, which should be enough for getting started. In reality it have a lot of things related to it like memory protection, paging, etc.

Cast int (*a)[4] to int *p

Is it legal to cast a pointer to an array of ints to an int pointer?
int arr[4];
int (*a)[4] = &arr;
int *p = (int*)a;
C 2018 6.3.2.3 7 says we can convert an int (*)[4] to an int *:
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined…
The alignment is necessarily correct since an array of int must have the alignment required for an int.
However, the only thing the C standard says about the value resulting from this conversion is:
… when converted back again, the result shall compare equal to the original pointer.
This means that an int * can temporarily hold the value of an int (*)[4]. If we execute:
int arr[4];
int (*x)[4] = &arr;
int *y = (int *) x;
int (*z)[4] = (int (*)[4]) y;
then we know x == z is true because the standard tells us that. But we do not know what y is. Because the standard permits different types of pointers to have different representations (use the bits that represent their values in different ways), it is possible that y has no useful meaning as an int *. The C standard does not say the converted pointer can be used to access objects.
Most C implementations either support this deliberately or as an artifact of how they are designed. However, in terms of what the C standard specifies, no guarantee is given.
If the original pointer's initialized to either NULL or a valid pointer to an int[4], then yes. Pointer casts must not violate alignment requirements lest you get UB. A cast such as what I've described won't violate such requirement ̶a̶n̶d̶ ̶f̶u̶r̶t̶h̶e̶r̶m̶o̶r̶e̶ ̶i̶t̶ ̶w̶i̶l̶l̶ ̶b̶e̶ ̶u̶s̶a̶b̶l̶e̶ ̶f̶o̶r̶ ̶d̶e̶r̶e̶f̶e̶r̶e̶n̶c̶i̶n̶g̶ ̶b̶e̶c̶a̶u̶s̶e̶ ̶i̶f̶ ̶t̶h̶e̶ ̶̶i̶n̶t̶(̶*̶a̶)̶[̶4̶]̶̶ ̶i̶s̶ ̶v̶a̶l̶i̶d̶ ̶a̶n̶d̶ ̶n̶o̶n̶n̶u̶l̶l̶ ̶t̶h̶e̶n̶ ̶t̶h̶e̶r̶e̶ ̶i̶n̶d̶e̶e̶d̶ ̶i̶s̶ ̶a̶n̶ ̶̶i̶n̶t̶̶ ̶a̶t̶ ̶̶(̶i̶n̶t̶*̶)̶a̶̶.
If you feel uneasy about pointer casts (as you should), you can effect the conversion in this case without casting by simply doing *a (will get int[4] which will decay to int*) or a[0] or &a[0][0] or &(*a)[0]. That way, you can also dereference the result while adhering to the letter of the standard.

Why type casting not required?

Below are following code written in c using CodeBlocks:
#include <stdio.h>
void main() {
char c;
int i = 65;
c = i;
printf("%d\n", sizeof(c));
printf("%d\n", sizeof(i));
printf("%c", c);
}
Why when printing variable c after it was assigned with int value (c = i), there no need for casting to be made?
A cast is a way to explicitly force a conversion. You only need casts when no implicit conversions take place, or when you wish the result to have another type than what implicit conversion would yield.
In this case, the C standard requires an implicit conversion through the rule for the assignment operator (C11 6.5.16.1/2):
In simple assignment (=), the value of the right operand is converted to the type of the
assignment expression and replaces the value stored in the object designated by the left
operand.
char and int are both integer types. Which in turn means that in this case, the rules for converting integers are implicitly invoked:
6.3.1.3 Signed and unsigned integers
When a value with integer type is converted to another integer type other than _Bool, if
the value can be represented by the new type, it is unchanged.
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or
subtracting one more than the maximum value that can be represented in the new type
until the value is in the range of the new type.
Otherwise, the new type is signed and the value cannot be represented in it; either the
result is implementation-defined or an implementation-defined signal is raised.
In your case, the new type char can be either signed or unsigned depending on compiler. The value 65 can be represented by char regardless of signedness, so the first paragraph above applies and the value remains unchanged. For other larger values, you might have ended up with the "value cannot be represented" case instead.
This is a valid conversion between integer types, so no cast is necessary.
Please note that strictly speaking, the result of sizeof(c) etc is type size_t and to print that one correctly with printf, you must use the %zu specifier.
This assignment is performed on compatible types, because char is not much more than a single byte integer, whereas int is usually 4bytes integer type (machine dependant). Still - this (implicit) conversion does not require casting, but You may loose some information in it (higher bytes would get truncated).
Let's examine your program:
char c; int i = 65; c = i; There is no need for a cast in this assignment because the integer type int of variable i is implicitly converted to the integer type of the destination. The value 65 can be represented by type char, so this assignment is fully defined.
printf("%d\n", sizeof(c)); the conversion specifier %d expects an int value. sizeof(c) has value 1 by definition, but with type size_t, which may be larger than int. You must use a cast here: printf("%d\n", (int)sizeof(c)); or possibly use a C99 specific conversion specifier: printf("%zu\n", sizeof(c));
printf("%d\n", sizeof(i)); Same remark as above. The output will be implementation defined but most current systems have 32-bit int and 8-bit bytes, so a size of 4.
printf("%c", c); Passing a char as a variable argument to printf first causes the char value to be promoted to int (or unsigned int) and passed as such. The promotion to unsigned int happens on extremely rare platforms where char is unsigned and has the same size as int. On other platforms, the cast is not needed as %c expects an int argument.
Note also that main must be defined with a return type int.
Here is a modified version:
#include <stdio.h>
#include <limits.h>
int main() {
char c;
int i = 65;
c = i;
printf("%d\n", (int)sizeof(c));
printf("%d\n", (int)sizeof(i));
#if CHAR_MAX == UINT_MAX
/* cast only needed on pathological platforms */
printf("%c\n", (int)c);
#else
printf("%c\n", c);
#endif
return 0;
}

How to print the address value of a pointer in a C program?

I'm trying to learn how to use the pointer in a C program; my example is as follows:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int * tab = (int*)malloc(sizeof(int)*5);
int a = 10;
int *p;
p = &a;
printf("the address of a is %d \n",&a);
printf("the address of a using the pointer is %p \n",p);
printf("the address of tab is %d \n",tab);
}
I'm trying to print the address of a, the address value inside of p and where the first byte of the tab begins.
I can get hexadecimal values when using "%p", but I'm willing the decimal value of the addresses.
Edit : On this Video image, someone has used "%d" to print a decimal value for a pointer address, and it has confused me.
To print a decimal version of an object pointer, 1st convert the pointer to an integer. Best to use the optional type uintptr_t.
The following type (uintptr_t) designates an unsigned integer type with the property that any valid pointer to void can be converted to this type (uintptr_t) ... C11dr §7.20.1.4 1
#include <inttypes.h>
uintptr_t d = (uintptr_t)(void *) &a;
Then print it.
Some info on PRIuPTR
printf("%" PRIuPTR "\n", d);
For pre-C99 code, consider a direct cast to unsigned long. #Barmar
OP later commented
"... i will try to manipulate the tab variable , and i will test if every cell in the tab is 4 byte , so may be i will do tab+8 bytes to get the value of a specific cell , here it's a simple example , with decimal it will be easy for me ."
This is a questionable approach as the decimalization of a pointer may not provide the continuous numeric model expected. This post this may be good for learning, but with OP providing more details in another post, even better ideas could be given for the higher level problem.
First, be aware that addresses are often "number-like" but might not be (e.g. remember the segment+offset notion of far addresses on 1980-era 16 bits x86 PCs).
Then, the integral type the most similar to pointers is intptr_t (signed) or uintptr_t (unsigned) - both from <stdint.h>.
You might cast that to a long long (hoping that they are not smaller than pointers), e.g.
printf("address of a in decimal is %lld\n", (long long) (intptr_t) (&a));
But really, why do you want to show an address in such a fashion? I see no need for it (e.g. debuggers or linkers are generally showing addresses in hexa, which is probably what %p does).
Notice that the C11 standard (see n1570, §7.21.6.2, p315) does not say much about %p for printing pointer:
The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.
I'm understanding the above in a way where printing Hello ⭔ for any pointer would be an acceptable and standard conforming behavior. In practice, implementations print pointers in a way similar to what linkers and debuggers do, and don't behave in a silly way (but I understand they could).
At last, the actual concrete "numerical" value of a pointer is not really important and can vary greatly from one execution to the next (e.g. because of ASLR).
For printing an "address" (actually a pointer) "%p" is the most common method (note the necessary cast to void*). If you need the address in decimal instead of hexadecimal, you can convert the pointer into an integral value; this is well defined in C (cf. this online C standard draft):
6.3.2.3 Pointers
(6) Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type.
So the code could look as follows:
int main(int argc, char *argv[]) {
int a =10;
int *p = &a;
p = &a;
unsigned long long addrAsInt = (unsigned long long)p;
printf("the adress of a is %llu \n",addrAsInt);
printf("the adress of a using the pointer is %p \n",(void*)p);
}
If you want to see the pointer as a decimal integer, cast it to unsigned long and print it with %lu format. While this isn't guaranteed by the standard, it should work in most implementations.
printf("the address of a is %lu\n", (unsigned long)&a);

If character constants are of type `int', why are they assigned to variables of type `char`?

The C11 standard says that character constants (e.g., 'x') are of type int, not char. This surprised and confused me (especially as a relative beginner). I came across this answer Why are C character literals ints instead of chars?, which somewhat cleared things up, but still left me wondering why it seems to be routine practice (at least in all the books and tutorials I've come across) to assign character constants to variables that are declared to be of type char. For example, why do we do
char initial = 's';
and not
int initial = 's';
And then, what happens when a constant of type int is assigned to a variable of type char? Is it switched into type char?
The fact that character literals are of type int is only a half of the story. The other half is that their value is in the range of char. This is critical, because if you assign
char a = 65;
you get no warning, but if you do
char b = 56789;
you get a warning.
why do we do char initial = 's' and not int initial = 's'?
This lets you avoid casting when assigning the variable to another variable of type char, or to an element of a char[] array:
char str[2];
str[0] = initial; // no cast when "initial" is of type "char"
There is one situation when you need to use int for variables storing char - when you use a getc / fgetc functionality, the result must be an int, not a char, in order to allow comparison with EOF.
Consider float x = 3.0; That sets a double 3.0 to a float. Code could have been float x = 3.0f;. The end result is the same.
Same with char ch = 5;. vs char ch = (char)5; In both case, ch gets the same value.
In the end, consider C was originally focused on types int, and double - that's it. Types like float, short, char, long ,... are just deviations from the truly core types of C. (Even unsigned, bool were afterthoughts.)
what happens when a constant of type int is assigned to a variable of type char? Is it switched into type char?
The constant remains the type it was. Assigning a constant of type int to a char does not change the type of the constant. What can change is the value from the int when the original int value is outside the range of char and then saved in a char.
If an int value is assigned to char variable, the value is converted to type char.
There are a few reasons for declaring a variable char rather than int. One is to save memory (although this is more relevant when used in an array or other aggregate). Another is to make it clear that it is intended to hold a char value. Another is to implicitly restrict the range of its value. And in some cases you may wish to take its address to obtain a char *, in which case you would not be able to use an int variable.

Resources