Not getting the expected results at pointer increment - c

Pointer increment not giving the right value, it points to indeterminate address.
Want to know why *p++= <value> not pointing to the value I want instead it points to something else
My code:
void run_exe() {
int i;
uint8_t buf[20] = {"0"};
uint8_t *p = NULL;
uint8_t tx_buf[4] = {1,1,1,1};
p = buf;
*p++ = 0x14;
*p++ = 0x20;
*p++ = 0x30;
*p++ = 0x40;
*p++ = 0x50;
*p++ = 0x60;
memcpy( p+6, tx_buf, sizeof(tx_buf));
// ARRAY_SIZE: is the macro just my array length.
for (i = 0; i < ARRAY_SIZE(buf); i++) {
printf("%d ", *(p+i));
}
}
I'm printing the decimal value of HEX but at least I'm expecting the correct value but I get indeterminate value.
I'm expecting the output like this.
14 20 30 40 50 60 1 1 1 1 0 0 0 0 0 0 0 0 0
Output:
0 0 0 0 0 0 1 1 1 1 0 0 0 0 255 127 0 0 0

You need an auxiliary pointer,
uint8_t *ptr;
p = buf;
ptr = p;
*p++ = 0x14;
and so on, because the ++ will modify the pointer's value.
Then,
for (i = 0; i < ARRAY_SIZE(buf); i++) {
printf("%d ", ptr[i]);
}
The ++ post-increment or pre-increment operator, makes the pointer p point to p + 1 after the expression is evaluated, so your p is NOT pointing to buf when you attempt to print it.
EDIT: Of course you can just do this too,
for (i = 0; i < ARRAY_SIZE(buf); i++) {
printf("%d ", buf[i]);
}
but I think the original answer explains the reason which is the important thing.
EXTRA: Also, I am 99.9% sure that this is wrong
uint8_t buf[20] = {"0"};
you meant,
uint8_t buf[20] = {0};
your compiler might be showing you a warning for this initialization which is faulty, because "0" has pointer type and even though it's convertible to a integer type, it mostly certainly doesn't fit a uint8_t so you have a overflow issue there.

Related

Please run this code and tell me why got this result

why the result of " (num >> i)& 1 " is 1 for the second loop?
main() {
char num = 5 ;
int i , count = 0 ;
for(i=0;i<8;i++){
if ((num >> i)& 1 )
count++;
}
printf("%d", count);
}
For starters pay attention to that the variable num itself is not being changed within the for loop
for(i=0;i<8;i++){
if ((num >> i)& 1 )
count++;
}
Its binary representation is
00000101
(Note take into account that the declaration
char num = 5 ;
differs from the declaration
char num = '5' ;
end note.)
In the first iteration of the loop when i is equal to 0 the shift operator has no effect so the if statement evaluates to logical true and the variable count will be incremented.
The variable count also will be incremented when i is equal to 2.
So as a result you will get that count is equal to 2 because in the internal representation of the variable num only two bits are set..
To make it more clearer rewrite the program the following way
#include <stdio.h>
int main(void)
{
char num = 5 ;
int count = 0 ;
for ( int i = 0; i < 8; i++ )
{
int result = (num >> i)& 1;
printf( "i = %d, result = %d\n", i, result );
if ( result ) count++;
}
printf( "\ncount = %d\n", count );
}
The program output is
i = 0, result = 1
i = 1, result = 0
i = 2, result = 1
i = 3, result = 0
i = 4, result = 0
i = 5, result = 0
i = 6, result = 0
i = 7, result = 0
count = 2
In fact the output from top to bottom shows the internal representation of the variable num starting from its less significant bit to the most significant bit.

IMG_Load or SDL_Surface only has one RGB channel

I'm trying to load an image file and grab the pixels from it, but it seems it only has pixels stored in the red channel and they don't match up with the original image.
I searched around and found another question on stack overflow. I ended up copy and pasting their solution in and it didn't work.
This is what I am expecting
This is what I get. Image is tiled.
IMG_GetError() doesn't return anything. I've tried both jpg and PNG. Not sure what is happening here and would like some guidence.
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch (bpp)
{
case 1:
return *p;
break;
case 2:
return *(Uint16 *)p;
break;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
break;
case 4:
return *(Uint32 *)p;
break;
default:
return 0; /* shouldn't happen, but avoids warnings */
}
}
IMG_Init(IMG_INIT_PNG);
SDL_Surface * img_test;
img_test = IMG_Load("resources/stonetiles_003_diff.png");
if(!img_test) {
printf("IMG_Load: %s\n", IMG_GetError());
}
int bpp = img_test->format->BytesPerPixel;
for (int i = 0; i < img_test->w; i++)
{
for (int j = 0; j < img_test->h; j++)
{
Uint8 data = getpixel(img_test, i, j);
SDL_Color rgb;
SDL_GetRGB(data, img_test->format, &rgb.r, &rgb.g, &rgb.b);
printf("%d %d %d\n", rgb.r, rgb.g, rgb.b);
}
}
}
Sample output of rgb values
22 0 0
21 0 0
34 0 0
49 0 0
52 0 0
42 0 0
46 0 0
48 0 0
47 0 0
53 0 0

Trying to print every combination of bits , given a variable

Lets say combinationlength=4.
My logic is create the array {0,0,0,0} add 1 to the last element until first element gets the value 1.Until then if with the addition of 1 the array[3] ends up in a 2 result then make it 0 and then traverse the array(reversed) given a counter variable and every first non 1 element make it 0 while making all elements before the value that first non 1 equal to 0.This is for 8 repetitions.How close am i?Can someone help me finish this?
Also this doesnt run for some reason.Nothing gets printed and ends after 2 seconds.
I just noticed i am skipping a step but anyways.
I want in every iteration to have an array like the sequence.And not added printf("0"); and shortcuts like that.
void print(int combinationlength){
int i,j,count;
int a=combinationlength-1;
int c=combinationlength-1;
int b;
int array[4]={0};
while(array[0]!=1){
array[a]++;
if(array[a]==2){
array[a]=0;
for(b=a;b<=c-1;b--){
if(array[b]==0)
array[b]=1;
}
c--;
}
for(count=0;count<combinationlength;count++){
printf("%d",array[count]);
}
printf("\n");
}
return 0;
}
UPDATED:(also updated my explanation above this ^^ block of code)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int i,j,count;
int a=4-1;
int c=4-1;
int b;
int array[4]={0};
while(array[0]!=1){
array[a]++;
if(array[a]==2){
array[a]=0;
for(b=a-1;b>c-1;b--){
if(array[b]==0) array[b]=1;
else array[b]=0;
}
c--;
}
for(count=0;count<4;count++){
printf("%d",array[count]);
}
printf("\n");
}
return 0;
}
The hardcoded number 4 is supposed to be the input variable.
So, I'm still not entirely sure I understand what you want. If I understood correctly, you want every combination of bits (i.e. zeros and ones) of a certain length. Doing the additions manually in an array feels very wasteful, so lets instead use what the CPU already has to offer - integer addition.
An example program, printing all the combinations of a certain length would look something like this:
#include <stdio.h>
void print(int len){
for (unsigned long sortOfAnArray = 0; sortOfAnArray < (1U << len); sortOfAnArray++) {
for (int i = len - 1; i >= 0; i--) {
printf("%lu", (sortOfAnArray >> i) & 1);
}
printf("\n");
}
}
int main(void) {
print(5);
return 0;
}
To explain the steps, sortOfAnArray is our integer, stored in binary, we add 1 to it on every iteration so that we get the different combinations.
In order to print it, we have to access elements individually, we do this with a combination of a bitshift and logical and (sortOfAnArray >> i) & 1. So, we shift the bits in the array by i to the right, and check if it has a 1 on the first position, in other words, we checked if sortOfAnArray[i]==1 (if this was an array).
We use unsigned due to the standard and long in case you want up to 64 bits available (although long long would be even safer there).
EDIT
To further explain how we extract a bit from the integer.
Assume we have the integer
`unsigned long long foo = 27`
if we look at the bit representation of that, we get 00...011011, where the total number of bits is 64, but there's just a lot of zeros, hence the dots. Now, say we want to know the value of the 1st bit from the right. We can find that out by using the logical and operation
`foo & 1`
This will apply the logical and to every pair of bits at the same position in the two integers (foo and 1), in this case this will give us 1:
foo -- 00...011011
1 -- 00...000001
foo & 1 -- 00...000001
If foo had 0 as the rightmost bit, the result would instead be 0, so this essentially allows us to read whether the first bit is set to 0 or 1.
How do we generalise this to the other bits?
We have two options, we can either move the bit in the 1 (1 << n shifts the 1 bit n moves to the left), if we use the logical and then, we will get 0 if foo has a 0 in the n-th position or some nonzero value (2^n) if it has a 1.
The other option is to instead shift the bits of foo to the right, the upside of doing this is if foo had a 1 in the n-th position, the result will now be 1 rather than 2^n, whereas if it was 0 the result is still 0. Other than that the two approaches are equivalent.
This is how we come up with the final solution, that is, to access the n-th element (0-based counting) as follows:
(foo >> n) & 1
we move the bits of foo to the right by n and look if the first bit is set to 0 or 1. Essentially, the integer is storing 64 bits (we don't need to use all of them, of course) the same way we would do that in an array, but the approach is much more efficient. Among other things, we don't need to implement our own addition for the array, as you had attempted initially.
Your problem statement is confusing:
if with the addition of 1 the array[3] ends up in a 2 result then make it 0 and then traverse the array(reversed) given a counter variable and every first non 1 element make it 0 while making all elements before the value that first non 1 equal to 0.
This basically means you want the first 0 element to remain 0 while making all elements before that first 0 set to 0.
As a consequence, the array contents would alternate between { 0, 0, 0, 0 } and { 0, 0, 0, 1 }, which is probably not the intent.
Let's assume your problem is to simulate a base-2 counter with 4 binary digits and you count from 0 to 8. Your code is a bit too complicated (pun intended ;-). You should simplify and use fewer index variables:
#include <stdio.h>
int main() {
int i;
int array[4] = { 0 };
while (array[0] != 1) {
for (i = 0; i < 4; i++) {
printf("%d ", array[i]);
}
printf("\n");
for (i = 4; i-- > 0; ) {
array[i] += 1;
if (array[i] == 2) {
array[i] = 0;
} else {
break;
}
}
}
return 0;
}
Output:
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
Note how you can write a for loop that counts down from the length of the array, enumerating all valid index values while using the exact length of the array and using a test i-- > 0 that is correct for both signed and unsigned types. This trick is sometimes referred to as the downto operator, not a real operator but one can make it look like one as i --> 0.
EDIT: to print the complete set of binary combinations, keep looping until i is -1:
#include <stdio.h>
int main() {
int i;
int array[4] = { 0 };
for (;;) {
for (i = 0; i < 4; i++) {
printf("%d ", array[i]);
}
printf("\n");
for (i = 4; i-- > 0; ) {
array[i] += 1;
if (array[i] == 2) {
array[i] = 0;
} else {
break;
}
}
if (i < 0) {
/* the array is too small, all combinations exhausted */
break;
}
}
return 0;
}
An integer already consists (most of the time) of 4 bytes = 32 bits. You can use a simple integer instead of an array.
However printing an integer in binary format is a bit tricky, I used the answer of this question to do it.
#include <stdio.h>
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
int main(void) {
int a = 0;
int limit = 4;
while( (a & (1 << limit)) == 0)
{
printf("0b"BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(a));
a++;
}
return 0;
}
Output:
0b00000000
0b00000001
0b00000010
0b00000011
0b00000100
0b00000101
0b00000110
0b00000111
0b00001000
0b00001001
0b00001010
0b00001011
0b00001100
0b00001101
0b00001110
0b00001111
Little explanation:
In the while loop I use a so called bit mask. (1 << limit) results in a binary 1 at the position limit, so in this case it would be 0b00010000. With the binary & I check if a has that bit, if yes the while loop ends.
Whenever I have to do something involving iteration over combinations, I automatically think of Grey Codes / reverse binary coding. Below is my own implementation (it uses a different formula than the wiki, but still covers all the values). Note they won't be in order, but it does cover all combinations 0->2^n-1 and it is very fast since it only needs to change one value each time.
#include <stdio.h>
int main(int argc, char** argv) {
unsigned int length = 4;
unsigned int array[4] = {0, 0, 0, 0};
int i, j;
for (i = 0; i < 1 << length; i++) {
array[__builtin_ctz(i)] ^= 1;
printf("Array Values: ");
for (j = 0; j < length; j++) {
printf("%d ", array[j]);
}
printf("\n");
}
return 0;
}
Output:
Array Values: 0 0 0 0
Array Values: 1 0 0 0
Array Values: 1 1 0 0
Array Values: 0 1 0 0
Array Values: 0 1 1 0
Array Values: 1 1 1 0
Array Values: 1 0 1 0
Array Values: 0 0 1 0
Array Values: 0 0 1 1
Array Values: 1 0 1 1
Array Values: 1 1 1 1
Array Values: 0 1 1 1
Array Values: 0 1 0 1
Array Values: 1 1 0 1
Array Values: 1 0 0 1
Array Values: 0 0 0 1
Note I use the __builtin_ctz() method to count trailing zeros quickly. I don't know if its implemented on any other compilers, but GCC supports it.

copying integers from char array depending on number of bytes in C

I have one character array of 8 bytes containing integer values. I need to copy the 1 byte to one integer variable, next 4 bytes to different integer variable, next 3 bytes to another integer variable.
I have used "memcpy" but the results are not proper.
My try:
unsigned char bytes[8];
int Data1 = 32769;
int Data2 = 65535;
int logic1 = 0;
int logic2 = 0;
int logic3 = 0;
memcpy(&bytes[0], &Data1, sizeof(Data1));
memcpy(&bytes[4], &Data2, sizeof(Data2));
//Value of bytes[] array after this operation is
//bytes[0] = 1
//bytes[1] = 128
//bytes[2] = 0
//bytes[3] = 0
//bytes[4] = 255
//bytes[5] = 255
//bytes[6] = 0
//bytes[7] = 0
memcpy(&logic1,&bytes,1);
memcpy(&logic2,&bytes + 1,4);
memcpy(&logic3,&bytes + 5,1);
My output should be :
logic1 = bytes[0]
logic2 = bytes[1] to bytes[4]
logic3 = bytes[5] to bytes[7]
I think you meant
memcpy( &logic1, &bytes[0], 1 );
memcpy( &logic2, &bytes[1], 4 );
memcpy( &logic3, &bytes[5], 3 );
Note that &bytes is a pointer to the whole array, so &bytes + 1 points beyond the end of the array, and &bytes + 5 is way beyond the end of the array. Hence you get undefined behavior, and unexplainable results.

Pass 2D array by reference

I want to be able to pass a 2D array to a function, and have it directly change the array in main, so pass by reference. When I try to compile, I get error: expected expression before { in the switch cases. (boardSize=10, but that is not known at compilation time)
void fillBoard(int **, int);
int main() {
int **board = malloc(sizeof(int *) * boardSize);
fillBoard(board, boardSize);
}
void fillBoard(int **board) {
int i, *row = malloc(sizeof(int) * boardSize);
for (i=0; i<boardSize; i++) {
board[i] = malloc(sizeof(int) * boardSize);
switch(i) {
case 1: row = {1,0,1,0,1,1,0,0,1,0}; break;
default: row = {0,0,0,0,0,0,0,0,0,0}; break;
}
board[i] = row;
}
}
There a many different ways to do this. The key is to keep track of what you are addressing where. You can use a single or double pointer to pass and fill board, it all depends on how you want to keep track of the elements. (while the 2-dimensional array, provides a convenience in referencing elements, all values are sequential in memory, and can be accessed with a 1-dimensional reference and offset).
There is one important suggestion when allocating memory for numeric arrays. You must always initialize all elements of the array to protect against attempting to access or dereference an uninitialized value (Undefined behavior). The simple way to do this is to allocate with calloc instead of malloc. calloc allocates and initializes all values to zero (NULL).
Also be aware of the need to track the memory you allocate over the life of your program and free the memory when you no longer need it. This will prevent memory leaks from developing. In a short bit of code like the following, the memory is freed when the program exits. If this were part of some larger code, you would need to free board and board2 when there data was no longer needed.
An example using your original array would be:
#include <stdio.h>
#include <stdlib.h>
#define boardSize 10
void fillBoard_p (int *a);
void fillBoard_p2p (int **a);
int main() {
int i = 0;
int j = 0;
/* declaring board as an integer pointer */
int *board = calloc (boardSize * boardSize, sizeof (*board));
/* declaring board as a pointer to pointer */
int **board2 = calloc (boardSize, sizeof (*board2));
for (i = 0; i < boardSize; i++) {
board2[i] = calloc (boardSize, sizeof (**board2));
}
fillBoard_p (board);
fillBoard_p2p (board2);
printf ("\nboard as an integer pointer:\n");
for (i = 0; i < boardSize * boardSize; i++) {
if (i % boardSize == 0)
printf ("\n %d", board[i]);
else
printf (" %d", board[i]);
}
printf ("\n");
printf ("\nboard2 as an pointer to integer pointer:\n\n");
for (i = 0; i < boardSize; i++) {
for (j = 0; j < boardSize; j++) {
printf (" %d", board2[i][j]);
}
printf ("\n");
}
printf ("\n");
return 0;
}
void fillBoard_p(int *a) {
// 0=WHITE, 1=BLACK
int i = 0;
int j = 0;
int b [][boardSize] = {
{1,0,1,0,1,1,0,0,1,0},
{1,0,1,1,0,0,1,1,1,0},
{0,0,1,0,1,0,1,0,1,1},
{1,1,0,1,1,0,1,0,0,0},
{0,0,1,0,0,0,1,1,0,1},
{1,1,0,1,1,0,0,1,1,0},
{0,0,1,0,0,1,1,0,1,1},
{0,0,1,0,0,1,0,0,0,0},
{1,1,1,1,0,0,1,1,1,1},
{0,1,0,0,1,1,0,0,0,1}
};
for (i = 0; i < boardSize; i++)
for (j = 0; j < boardSize; j++)
a[i*boardSize+j] = b[i][j];
}
void fillBoard_p2p (int **a) {
// 0=WHITE, 1=BLACK
int i = 0;
int j = 0;
int b [][boardSize] = {
{1,0,1,0,1,1,0,0,1,0},
{1,0,1,1,0,0,1,1,1,0},
{0,0,1,0,1,0,1,0,1,1},
{1,1,0,1,1,0,1,0,0,0},
{0,0,1,0,0,0,1,1,0,1},
{1,1,0,1,1,0,0,1,1,0},
{0,0,1,0,0,1,1,0,1,1},
{0,0,1,0,0,1,0,0,0,0},
{1,1,1,1,0,0,1,1,1,1},
{0,1,0,0,1,1,0,0,0,1}
};
for (i = 0; i < boardSize; i++)
for (j = 0; j < boardSize; j++)
a[i][j] = b[i][j];
}
output:
$ ./bin/fillboard
board as an integer pointer:
1 0 1 0 1 1 0 0 1 0
1 0 1 1 0 0 1 1 1 0
0 0 1 0 1 0 1 0 1 1
1 1 0 1 1 0 1 0 0 0
0 0 1 0 0 0 1 1 0 1
1 1 0 1 1 0 0 1 1 0
0 0 1 0 0 1 1 0 1 1
0 0 1 0 0 1 0 0 0 0
1 1 1 1 0 0 1 1 1 1
0 1 0 0 1 1 0 0 0 1
board2 as an pointer to integer pointer:
1 0 1 0 1 1 0 0 1 0
1 0 1 1 0 0 1 1 1 0
0 0 1 0 1 0 1 0 1 1
1 1 0 1 1 0 1 0 0 0
0 0 1 0 0 0 1 1 0 1
1 1 0 1 1 0 0 1 1 0
0 0 1 0 0 1 1 0 1 1
0 0 1 0 0 1 0 0 0 0
1 1 1 1 0 0 1 1 1 1
0 1 0 0 1 1 0 0 0 1
Additionally, since a 2-D array is stored sequentially in memory, you can take advantage of that fact and make use of memcpy (in string.h) to fill the array passed to your function. This can reduce your function to:
void fillBoard_mc (int *a) {
// 0=WHITE, 1=BLACK
int b [][boardSize] = {
{1,0,1,0,1,1,0,0,1,0},
{1,0,1,1,0,0,1,1,1,0},
{0,0,1,0,1,0,1,0,1,1},
{1,1,0,1,1,0,1,0,0,0},
{0,0,1,0,0,0,1,1,0,1},
{1,1,0,1,1,0,0,1,1,0},
{0,0,1,0,0,1,1,0,1,1},
{0,0,1,0,0,1,0,0,0,0},
{1,1,1,1,0,0,1,1,1,1},
{0,1,0,0,1,1,0,0,0,1}
};
memcpy (a, b, boardSize * boardSize * sizeof (int));
}
Were it not for the particularity of the compiler and pointer decay, you could simply use a statically declared array, such as:
int board[boardSize][boardSize] = {{0}};
passing the address of the array to your function (becoming a 3-star programmer):
fillBoard (&board);
with a function similar to:
void fillBoard (int *a[][boardSize]) {
// 0=WHITE, 1=BLACK
int b [][boardSize] = {
{1,0,1,0,1,1,0,0,1,0},
{1,0,1,1,0,0,1,1,1,0},
{0,0,1,0,1,0,1,0,1,1},
{1,1,0,1,1,0,1,0,0,0},
{0,0,1,0,0,0,1,1,0,1},
{1,1,0,1,1,0,0,1,1,0},
{0,0,1,0,0,1,1,0,1,1},
{0,0,1,0,0,1,0,0,0,0},A
{1,1,1,1,0,0,1,1,1,1},
{0,1,0,0,1,1,0,0,0,1}
};
memcpy (a, b, boardSize * boardSize * sizeof (int));
}
Due to pointer decay (board[10][10] => board[*][10]), you will receive an incompatible pointer type warning, despite the function successfully copying the memory as intended. Code that does not compile without warning, should not be relied on in practice.

Resources