Casting an int array into a char pointer in c - arrays

I ran through these few lines of code in C:
int tab[]={4,6,8,9,20};
char *p;
p=(char*)tab
And the question was how to print the value of 20 using the pointer p.
So i used a for loop to see what's going on with p
for(int i=0;i<20;i++){
printf("%d ",p[i]);
}
and i got this output:
4 0 0 0 6 0 0 0 8 0 0 0 9 0 0 0 20 0 0 0
i want to understand the logic behind those zeros appearing.

You are almost certainly using an architecture where int is 4 bytes, and a little-endian architecture where the "smallest" byte is stored first.
So the int value 4 is stored as:
+----+----+----+----+
| 4 | 0 | 0 | 0 |
+----+----+----+----+
The int value 20 gets stored as:
+----+----+----+----+
| 20 | 0 | 0 | 0 |
+----+----+----+----+
Your entire array in memory looks like:
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| 4 | 0 | 0 | 0 | 6 | 0 | 0 | 0 | 8 | 0 | 0 | 0 | 9 | 0 | 0 | 0 | 20 | 0 | 0 | 0 |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
Now, when you iterate over those 20 bytes as characters (and thus one byte at a time) the results should no longer be surprising.

On your machine, the sizeof an int is 4 bytes, and sizeof a char is by definition 1.
So with p, you're printing an int byte by byte.
"And the question was how to print the value of 20 using the pointer p."
As for that:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int tab[] = {4, 6, 8, 9, 20};
char *p = 0;
/* The type that & returns is a
* pointer type, in this case, a
* pointer to the 4th element of
* the array.
*/
p = (char*) &tab[4];
/* As %d expects an int, we cast
* p to an int *, and then
* dereference it.
*/
printf("%d\n", *(int *)p);
return EXIT_SUCCESS;
}
Output:
20
Edit: The above code is endian-dependent.

Related

How to add items to array in a function using pointers?

I am trying to write this function that takes an array input and assigns random numbers between 1-52 to the array. Then prints back the numbers. I get an error message on the 4th line that says expression is not assignable. Is my use of pointers incorrect or is it not possible to add content to array with pointers?
void shuffleDeck(int *deck[]) {
int i;
for(i=0;i<=52;i++)
rand()%53 = deck[i]; // I get an error message on this line
}
int main() {
srand(time(NULL));
int deck[2000];
shuffleDeck(deck);
int i;
for(i=0;i<=52;i++){
printf("%d", deck[i]);
}
return 0;
}
Assigment direction is from right to left
So in this expression
deck[i] = rand()%52 + 1;
First is called function rand()
Then the result of function %52
Then 1 is added
And finnally its assigned to deck[i]
Array (what you have in main) is
0 1 2 3 4
+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+
^-------------------------- arr[0]
While Array of pointers (what your function expects) is
0 1 2 3 4
+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 0
+---+---+---+---+---+
------^
| +---+---+---+---+---+
| | 0 | 0 | 0 | 0 | 0 | 1
| +---+---+---+---+---+
| +---+---+---+---+---+
| | 0 | 0 | 0 | 0 | 0 | 2
| +---+---+---+---+---+
|
----------------------------- arr[0][0]
When array is passed to function, then arr[] and *arr are the same. But only as function arguments!
%53 returns 0-52,so if you need 1-52, use %52 + 1 (0-51 + 1 = 1-52)
If you cant solve it, here is code with fixed bugs.
void shuffleDeck(int deck[]) {
int i;
for(i=0;i<=52;i++)
deck[i] = rand()%52 + 1;
}
int main() {
srand(time(NULL));
int deck[2000];
shuffleDeck(deck);
int i;
for(i=0;i<=52;i++){
printf("%d", deck[i]);
}
return 0;
}

Why the first prime number always becoming 1 instead of 2

Here i am trying to implement sieve of erastosthene in c.The program works fine except one major problem.I manually set the first prime number to be of value 2.But at the end when i loop through all the prime numbers array and print them ,the first value becomes 1 instead of 2.Can't figure out why this problem arises.Any help would be much appreciated.
#include<stdio.h>
#include<math.h>
int main(){
int n = 64;
int i,j,limit=sqrt(n)+2,nPrime=0;
int prime[50]={0},mark[64]={0};
mark[1]=1;
prime[nPrime++] = 2;
printf("%d\n",prime[0]); // initialized to 2
for(i=4;i<=n;i=i+2){
mark[i] = 1;
}
for(i=3;i<=n;i=i+2){
if(!mark[i]){
prime[nPrime++] = i;
if(i<=limit){
for(j=i*i;j<=n;j=j+i*2){
mark[j]=1;
}
}
}
}
int k;
int size = sizeof(prime)/sizeof(prime[0]);
printf("%d\n",prime[0]); // changed to 1;
for(k=0;k<size && prime[k]!=0;k++){
printf("%d ",prime[k]);
}
}
The problem is in this loop:
for(i=4;i<=n;i=i+2) {
mark[i] = 1;
}
The condition should be i < n, because with <= it will take the value 64, and that would be out of bounds.
When you set mark[64] = 1 you are modifying memory that does not belong to the mark array, in this case it turn out to be the first element of the prime array. If you test out other indexes, you could end up getting a segfault.
If you set manually mark[64] = 56, you will see that prime[0] == 56
Because local variable are declared on stack, in your case the variable mark[64] which is an array of 64 integer (64 * 4 = 256 bytes) occupies the first 256 bytes of the stack then the array prime (50 * 4 = 200 bytes) occupies the next 200 bytes as shown below:
Stack
|-----------|
| other |
| variables |
| |
prime[49]->|-----------| addr = 0x000001C8
| |
| prime |
|(200 bytes)|
prime[0]->| |
mark[63]->|-----------| addr = 0x00000100
| |
| |
| mark |
|(256 bytes)|
| |
mark[0]->|-----------| addr = 0x00000000
When you write mark[64] = 1, you are actually writing the four bytes of prime[0] = 1.

Removing the leading zeroes of a number stored in string

struct number {char digits[11];};
The following method removes leading zeroes from (*a).digits
void remove_zero(struct number *a);
Example: (*a).digits 000013204 ---> 13204
My approach is to define a variable b equals to (*a).digits, start seaching for the first non-zero number in b, then replace (*a).digits with the rest of b. However, I am having trouble implementing the code
void remove_zero(struct number *a) {
char b = (*a).digits;
while (b){ // <--- (b) indicates that it hasnt reached the terminator,right?
if (b != '0')
{ //<-- here is where to replace (*a).digits with the rest of b, but how to?
break;
}
}
}
So you have an array that contains e.g.
+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 1 | 3 | 2 | 0 | 4 | \0| |
+---+---+---+---+---+---+---+---+---+---+---+
And you want it to contain
+---+---+---+---+---+---+---+---+---+---+---+
| 1 | 3 | 2 | 0 | 4 | \0| | | | | |
+---+---+---+---+---+---+---+---+---+---+---+
From the "images" above, it should be pretty clear that this can be done using a simple movement of the data.
So one solution is to find the first non-zero character, and move from that to the beginning of the array.
In general it's clearer to deference a pointer to a struct and access its attributes using the -> operator, e.g. rather than
char b = (*a).digits;
do this
char *b = a->digits;
Note that digits is an array of chars, so b needs to be an array of chars, or a pointer to a char as shown here.
So:
void remove_zero(struct number *a)
{
char *b = a->digits;
char *end = a->digits + sizeof a->digits - 1;
while (b < end && *b == '0')
b++;
if (b != a->digits)
{
size_t n = end - b;
memmove(a->digits, b, n);
a->digits[n] = '\0';
}
}

Does typecasting have no effect in statement 1 in the below Code?

#include<stdio.h>
int main()
{
int arr[3] = {2, 3, 4};
char *p;
p = arr;
p = (char*)((int*)(p));
printf("%d, ", *p);
p = (int*)(p+1); //............statement 1
printf("%d", *p);
return 0;
}
In the above code, p = (int*)(p+1); means character pointer is type cast to integer pointer. So when we dereference p, It fetches the contents up to next int size (2 bytes or 4 bytes, depending on compiler). But when I am solving this question at www.indiabix.com, they have given
answer: 2, 0
How it can be 2, 0? As per my analysis,the answer should be 2, 3. Can anyone explain what should be the correct answer and why?
Let's say an int takes four bytes.
In a little endian system, the memory layout of arr looks like:
| | <--- one byte
+---+---+---+---+---+---+---+---+---+---+---+---+
| 2 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 4 | 0 | 0 | 0 |
+---+---+---+---+---+---+---+---+---+---+---+---+
In a big endian system, the memory layout of arr looks like:
| | <--- one byte
+---+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 2 | 0 | 0 | 0 | 3 | 0 | 0 | 0 | 4 |
+---+---+---+---+---+---+---+---+---+---+---+---+
In a little endian system,
*p = 2;
*(p+1) = 0;
In a big endian system,
*p = 0;
*(p+1) = 0;
Depending on your platform, the output will be:
2 0
or
0 0
The code you have is perhaps meant to confuse. The line
p = (char*)((int*)(p));
doesn't do a damn thing.
The line
p = (int*)(p+1);
has the same effect as:
p = p+1;

What does "char *t = s + len" mean?

I'm going through a programming book and I'm wondering what a line of code does. There are no comments in the book or explanations about what it's supposed to do.
Below is a function that takes a character array and prints it backwards.
void print_reverse (char *s)
{
size_t len = strlen(s);
char *t = s + len -1; // I don't understand what this line is doing
while (t >= s) {
printf("%c", *t);
t = t - 1;
}
puts("");
}
Let's say s is the string "PaxDiablo", stored in memory at location 1 thus:
s
|
V
+---+---+---+---+---+---+---+---+---+----+
| P | a | x | D | i | a | b | l | o | \0 |
+---+---+---+---+---+---+---+---+---+----+
Address: 1 2 3 4 5 6 7 8 9 10
The expression t = s + len - 1 (where len is 9 in this case) sets t to eight characters past s.
s t
| |
V V
+---+---+---+---+---+---+---+---+---+----+
| P | a | x | D | i | a | b | l | o | \0 |
+---+---+---+---+---+---+---+---+---+----+
Address: 1 2 3 4 5 6 7 8 9 10
In other words, it gives you the address of the last character in the string.
The rest of the code then iterates over the string in a backwards direction, by decrementing t until it passes s.
Technically, this is undefined behaviour since you're only every supposed to compare pointers where they point to the same array on one character beyond (here we are comparing t where it's one character before the array), but you'd struggle to find a system on which this didn't work.
As Potatoswatter (I absolutely love some of the names people choose here on SO) points out in a comment, you can avoid that comparison by using the do {} while construct rather than while {}:
#include <stdio.h>
#include <string.h>
void printReverse (char *str) {
size_t len = strlen (str);
if (len != 0) {
char *pStr = str + len;
do {
putchar (*(--pStr));
} while (pStr > str);
}
putchar ('\n');
}
Let's say s points to the string "Hello". In memory, it looks like:
s --> [ H | e | l | l | o | \0 ]
Now, char *t declares a new pointer variable to a char value, that is initialized with s + len - 1, which is:
s ------ ------- s + 5 // (len is 5 since strlen("Hello") is 5)
| |
[ H | e | l | l | o | \0 ]
|
------------ finally, t = s + len - 1

Resources