I don't understand why some pointer addresses are like this - c

I'm studying pointer in C language and I have some questions.
#include <stdio.h>
int main()
{
char c = 'A';
char* pc = &c;
char** ppc = &pc;
printf("%p %p\n", pc, ppc);
printf("%p %p\n", pc + 1, ppc + 1);
printf("%p %p\n", &c, &c + 1);
printf("%p %p\n", &pc, &ppc);
printf("%p %p\n", &pc + 1, &ppc + 1);
return 0;
}
In this code, let's say that
&c = 0117FE7B
&pc = 0117FE6C
&ppc = 0117FE60
I thought some answers will be like this:
ppc + 1 = 0117FE6D
&pc + 1 = 0117FE6D
&ppc + 1 = 0117FE61
but the correct answer was like this:
ppc + 1 = 0117FE70
&pc + 1 = 0117FE70
&ppc + 1 = 0117FE64
and I don't understand why. Can someone explain this for me?
(My computer is using 64 bit windows OS.)

Pointer arithmetic is done in terms objects, not bytes. If p evaluates to the address of a 4-byte int object, then p + 1 evaluates to the address of the next 4-byte int, not the next byte:
int x; // assume 4-byte int
int *ip = &x;
short s; // assume 2-byte short
short *sp = &s;
char c;
char *cp = &c;
+---+ +---+ +---+
x : | | <-- ip s : | | <-- sp c : | | <-- cp
+---+ +---+ +---+
| | | | | | <-- cp + 1
+---+ +---+ +---+
| | | | <-- sp + 1 | |
+---+ +---+ +---+
| | | | | |
+---+ +---+ +---+
| | <-- ip + 1 | | | |
+---+ +---+ +---+
| | | | | |
+---+ +---+ +---+
| | | | | |
+---+ +---+ +---+
| | | | | |
+---+ +---+ +---+
So depending on the size of the pointed-to type, p + 1 will either give the address + 1, or the address + 4, or the address + 8, etc.
Remember, the array subscript operation a[i] is defined as *(a + i) - given a starting address a, offset i objects (not bytes!!) from that address and deference the result.

Related

*a++ = *b++ (what does it mean, how it works)

What would be the values after performing this operation?
#include <stdio.h>
int main() {
int *a = 0;
int *b = 3;
*a++ = *b++;
printf("%d", a);
printf("%d", b);
return 0;
}
The code above gives me a segmentation fault.
*a++ = *b++ (what does it mean, how it works)
*a++ = *b++;
means
*(a++) = *(b++);
x++ increments x and returns the original value. So the following is equivalent:
*a = *b; // Copy the `int` to which `b` points into the `int` to which `a` points.
a = a + 1; // Make `a` point to the following `int`.
b = b + 1; // Make `b` point to the following `int`.
Before: After:
a a
+----------+ +----------+ +----------+ +----------+
| ---------->| x | | ------+ | p |
+----------+ +----------+ +----------+ | +----------+
| y | +--->| y |
+----------+ +----------+
| | | |
b b
+----------+ +----------+ +----------+ +----------+
| ---------->| p | | ------+ | p |
+----------+ +----------+ +----------+ | +----------+
| q | +--->| q |
+----------+ +----------+
| | | |
The code above gives me a segmentation fault.
You assigned garbage to a and b. 0 as a pointer is the NULL pointer, and 3 isn't a valid pointer.
Given
#include <stdio.h>
int main() {
int *a = 0;
int *b = 3;
*a++ = *b++;
printf("%d", a);
printf("%d", b);
return 0;
}
the printed values can not be predicted as the code invokes undefined behavior in multiple ways.
First, both *a and *b invoke undefined behavior by dereferencing invalid pointers - a is initialized to a null pointer value, and b is initialized to point to address 3, which is almost certainly invalid also.
Second,printf("%d", a); invokes undefined behavior by trying to print an int * variable with the %d format specifier for int. The proper code would be
printf("%p", ( void * ) a);
It's not clear what the currently-posted code is supposed to do.

Union value in C

Can somebody explain to me what happens with br agument in union, after assigning str.a and str.b? We need to set that value before calling the function above? I tried to run the code in simulator https://pythontutor.com/render.html#mode=display which says that the value of br is 516 before calling the function. How is that possible?
#include <stdio.h>
void f(short num, short* res){
if (num){
*res = *res * 10 + num%10;
f(num / 10, res);
}}
typedef union {
short br;
struct {
char a, b;
} str;
} un;
void main() {
short res = 0; un x;
x.str.a = 4; x.str.b = 2;
f(x.br, &res); x.br = res;
printf("%d %d %d\n", x.br, x.str.a, x.str.b);}
Assuming that char is one byte and short is two bytes (the most common), then it's really simple.
Begin by drawing out the members of the union on a piece of paper, one member next to the other. Something like this:
br str
+---+ +---+
| | | | a
+---+ +---+
| | | | b
+---+ +---+
Now we do the assignments:
x.str.a = 4;
x.str.b = 2;
And write the results in the drawing:
br str
+---+ +---+
| 4 | | 4 | a
+---+ +---+
| 2 | | 2 | b
+---+ +---+
Assuming little endianness like on a normal x86 or x86-64 system, then the value of br will be 0x0204 which is 516 in decimal.
So that's where the value 516 is coming from.
The value of the short will depend on the computer's endianess. On a little endian machine, a will correspond to the least significant byte and b to the most significant. Thus when those two bytes are converted to a short, you get the number 0x0204 = 516 decimal.
As a side note, it is a bad idea to use short and char since those may be signed and negative. Use uint16_t and uint8_t instead, whenever dealing with binary arithmetic.
If you put some effort into your debugging you would see what is going on:
void f(short num, short* res)
{
if (num)
{
*res = *res * 10 + num%10;
f(num / 10, res);
}
}
typedef union
{
short br;
struct
{
char a, b;
};
} un;
int main(void)
{
short res = 0; un x;
x.a = 4; x.b = 2;
printf("Before br=0x%04x (%d) a=0x%02x b=0x%02x res = %d 0x%x\n", x.br, x.br, x.a, x.b, res, res);
f(x.br, &res); x.br = res;
printf("After br=0x%04x a=0x%02x b=0x%02x res = %d 0x%x\n", x.br, x.a, x.b, res, res);
}
result:
efore br=0x0204 (516) a=0x04 b=0x02 res = 0 0x0
After br=0x0267 a=0x67 b=0x02 res = 615 0x267
Do your br was 516 and it was reversed by the f function becoming 615 which is 0x0276. It contains of two bytes 0x02 and 0x67.
Your computer is little-endian so the first byte is 0x67 and the second one is 0x02 because this system stores the least significant byte first.

Program using dynamic memory allocation

I have the below program in C. How did p[0][0] become 1? Can somebody help in understanding?
#include <stdio.h>
#include<stdlib.h>
main()
{
int i,j;
int **p=(int **)malloc(2 * sizeof(int *));
p[0]=(int*) malloc(2*sizeof(int));
p[1]=p[0];
for(i=0;i<2;i++)
for(j=0;j<2;j++)
{
p[i][j]=i+j;
printf("%d,%d,%d",i,j,p[i][j]);
printf("\n");
}
printf("%d,%d,%d",i,j,p[0][0]);
}
the output is as below
0,0,0
0,1,1
1,0,1
1,1,2
2,2,1
The same pointer is assigned to p[0] and p[1]. This means p[0] and p[1] points at the same array. Therefore updates done via p[1] is also visible via p[0].
In the second iteration of outer for loop, 1 is assigned to p[1][0]. This makes p[0][0] to be 1.
After the following lines of code:
int **p=(int **)malloc(2 * sizeof(int *));
p[0]=(int*) malloc(2*sizeof(int));
p[1]=p[0];
this is what you have in memory:
int ** int * int
+---+ +---+ +---+
p: | | ------> | | p[0] -+-> | | p[0][0], p[1][0]
+---+ +---+ | +---+
| | p[1] -+ | | p[0][1], p[1][1]
+---+ +---+
p[0] and p[1] point to the same 2-element array, so anything you write to p[0][i] is reflected in p[1][i] and vice-versa.
What you probably meant to do was something like
int **p = malloc( 2 * sizeof *p ); // cast not necessary, sizeof *p == sizeof (int *)
p[0] = malloc( 2 * sizeof *p[0] );
p[1] = malloc( 2 * sizeof *p[1] );
which would give you
int ** int * int
+---+ +---+ +---+
p: | | ------> | | p[0] ----> | | p[0][0]
+---+ +---+ +---+
| | p[1] --+ | | p[0][1]
+---+ | +---+
|
| +---+
+-> | | p[1][0]
+---+
| | p[1][1]
+---+

C. for loop with chars

Can you explain these outputs?
1)
char s[]="TvNnFs",*p;
for(p=&s[5];p>=s;p--)
--*p;
puts(s);
OUTPUT: SuMmEr
2)
char s[]="TvNnFs",*p;
for(p=&s[5]; p>=s; p--)
((--*p)<'a') ? (*p+=('a'-'A')) : (*p);
puts(s);
OUTPUT:summer
This
char s[]="TvNnFs",*p;
where s is an array of characters and p is character pointer, is looks like below
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
------------------------------------------
| T | v | N | n | F | s | \0 |
------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106.. (assume 0x100 is base address of s)
Next, the for loop
for(p=&s[5];p>=s;p--)
--*p;
Here p=&s[5] the pointer p points to address of s[5] i.e 0x105. Next is p>=s i.e 0x105 >= 0x100 which is true, then --*p executes i.e first *p that means value at 0x105 memory location which is s and decrements on that will makes s[5] as r.
Now char array s looks like
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
---------------------------------------------
| T | v | N | n | F | r(new)| \0 |
---------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
Note : you might interested to know that by doing --*p how does s got affected ? Its because p is pointing or holding the address of s i.e whatever changes are done on *p will affect indirectly to s.
After that p-- happens i.e p now points to one location previous than before i.e 0x104. Same operation will happens until p reach to s i.e 0x100 >= 0x100. Finally char array s looks like
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
-------------------------------------------
| S | u | M | m | E | r | \0 |
-------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
Hence it prints SuMmEr.
Case 2 :
char s[]="TvNnFs",*p;
for(p=&s[5]; p>=s; p--)
((--*p)<'a')?(*p+=('a'-'A')):(*p);
puts(s);
Here
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
------------------------------------------
| T | v | N | n | F | s | \0 |
------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
|
p points here
For 0x105 >= 0x100 : this
((--*p)<'a')?(*p+=('a'-'A')):(*p);
is ternary operator i.e first ((--*p)<'a') executes, if it results in true then (*p+=('a'-'A')) will be the output else (*p). So Here it looks like ((--*p)<'a') i.e 'r' < 'a' which is false so just (*p) but s[5] got changed after this due to --*p.
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
------------------------------------------
| T | v | N | n | F | r | \0 |
------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
|
p points here due to p--
Next, For 0x104 >= 0x100 : this
((--*p)<'a')?(*p+=('a'-'A')):(*p);
'E' < 'a' i.e 70 < 97 which is true so this (*p+=('a'-'A')) gets execute i.e
*p = *p + ('a' - 'A')
= 'E' + (97 - 65)
= 'E' + 32
*p = 'e' /* now s[4] overwritten by e(previously F) */
Now array looks like
s[0] s[1] s[2] s[3] s[4] s[5] s[6]
------------------------------------------
| T | v | N | n | e | r | \0 |
------------------------------------------
s 0x100 0x101 0x102 0x103 0x104 0x105 0x106..
|
p points here due to p--
Same operation hoes on until 0x100 >= 0x100.

How can I pass a structure's array in the right way to my function?

I am trying to pass a structure's array to a function, but it gives me an error when i becomes 1, acces violation.
Here is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
typedef struct {
int locuri;
int putere;
char marca[50];
char culoare[50];
int an_fabricatie;
}automob;
void aloca(automob **autos, int n)
{
*autos = (automob*)malloc(sizeof(automob)*n);
if (autos == NULL) {
exit(1);
}
}
void read_autos(const char* filename, automob **A, int *n)
{
FILE *f_in = fopen(filename, "r");
int i = 0, aux;
if (f_in == NULL) {
printf("Nu s-a gasit fisierul!");
_getch();
exit(0);
}
fscanf(f_in, "%d", n);
aloca(A, *n);
while (i < (*n)) {
fscanf(f_in, "%d", &A[i]->locuri);
fscanf(f_in, "%d", &A[i]->putere);
fscanf(f_in, "%s", &A[i]->marca);
fscanf(f_in, "%s", &A[i]->culoare);
fscanf(f_in, "%d", &A[i]->an_fabricatie);
i++;
}
}
void main()
{
int n;
automob *A;
read_autos("autos.in", &A, &n);
_getch();
}
I think the pointer A is not allocated properly but I really don't know. Do you have any ideas? Because this works when I write it in the main function but does not work if I right it in another function like read_autos.
A[i] -> locuri means (* A[i]).locuri; this would make sense if A was an array of pointers to automob; but it isn't. You want (* A)[i].locuri. And so on for the other fields.
fscanf(f_in, "%d", &(* A)[i].locuri);
fscanf(f_in, "%d", &(* A)[i].putere);
fscanf(f_in, "%s", (* A)[i].marca);
fscanf(f_in, "%s", (* A)[i].culoare);
fscanf(f_in, "%d", &(* A)[i].an_fabricatie);
What you wrote:
+------+ +-------+ +--------------------------------------------+
| A -----> | A[0] -----> | locuri | putere | marca | culoare | an_fab |
+------+ | | +--------------------------------------------+
+-------+ +--------------------------------------------+
| A[1] -----> | locuri | putere | marca | culoare | an_fab |
| | +--------------------------------------------+
+-------+ +--------------------------------------------+
| A[2] -----> | locuri | putere | marca | culoare | an_fab |
| | +--------------------------------------------+
+-------+ +--------------------------------------------+
| A[3] -----> | locuri | putere | marca | culoare | an_fab |
| | +--------------------------------------------+
+-------+
What you want:
+------+ +-------+ +--------------------------------------------+
| A -----> | * A -----> [0] | locuri | putere | marca | culoare | an_fab |
+------+ +-------+ +--------------------------------------------+
[1] | locuri | putere | marca | culoare | an_fab |
+--------------------------------------------+
[2] | locuri | putere | marca | culoare | an_fab |
+--------------------------------------------+
[3] | locuri | putere | marca | culoare | an_fab |
+--------------------------------------------+
(It is a comment but I do not have 50 reputation, so I answer and you could convert it as a comment)
When I have such problem and it happens, I do not hesitate to simply print pointer value.
For example, in your case :
printf("sizeof %I64u\n",sizeof(automob));
printf("Global Addr %I64u\n",*A);
printf("1st elt Addr %I64u\n",&(*A)[0]);
printf("2nd elt Addr %I64u\n",&(*A)[1]);
printf("1st elt / 1st field Addr %I64u\n",&(*A)[0].locuri);
printf("2nd elt / 2nd field Addr %I64u\n",&(*A)[1].locuri);

Resources