What's wrong with the pointers - c

I am learning pointers in C language. I have written a simple code of pointers using. I have no errors, but the program iz freezing in the middle of execution. What could be the reason for that?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
void main()
{
int i;
int *i2;
i2 = &i;
int z;
int *z2;
z2 = &z;
int b = 0;
int *b2;
b2 = &b;
char ch[250];
//char *ch2;
//ch2 = &ch;
printf("%s\n", " Enter line not longer than 250 characters");
gets_s(ch);
for (*i2 = 0; *i2<10; i2++)
{
if (*i2>4)
{
*z2 = *i2;
*b2++;
break;
}
}
printf("%d%c", *b2, ch[*z2]);
}

A big problem is your for loop:
for (*i2 = 0; *i2<10; i2++)
i2++ increments the value of the pointer (making it point to something other than i), not the thing being pointed to. You need to change that line to
for (*i2 = 0; *i2<10; (*i2)++)
The parentheses around *i2 are necessary, because the postfix ++ operator has higher precedence than the unary * operator. *i2++ would be parsed as *(i2++), which is not what you want.

for (*i2 = 0; *i2<10; i2++)
should be
for (*i2 = 0; *i2<10; (*i2)++)
NOTE:
Use the standard definition of main()
int main(void) //if no command line arguments.

You asked a second question when you edited your original question (that edit has now been reversed so the actual question has disappeared).
Basically you asked why the printf statement was not returning the expected value.
At that time you had this code:
for (*i2 = 0; *i2<10; (*i2)++)
{
if (*i2>4)
{
*z2 = *i2;
*b2++;
break;
}
}
printf("%d%c\n", b2, ch[z]);
b2 is a pointer ... int *b2;
Now you assign a value to b2 ... b2 = &b;
So now b2 contains the address b and your printf statement prints this address (albeit in integer format '%d' rather than as a pointer %p)
To get the value held in 'b' which is 'pointed to by 'b2', you need to dereference ... *b2
But ... note that you have changed the pointer *b2 with this statement ... *b2++
That statement changed the value of the pointer, not the value of b which it originally pointed to and now *b2 will be undefined.
Change *b2++ to (*b2)++ and change printf b2 to printf *b2
and the result is b + 1 which will be 1 as b was originally set to 0.

Related

printf with arguments functions returning a pointer to char

Hi I tried to setup a code like
#include <stdio.h>
struct _data;
typedef struct _data data;
typedef struct _data {
double x;
double y;
} data;
const char* data_tostring(data* a) {
static char buffer[255];
sprintf(buffer, "%f %f", a->x, a->y);
return buffer;
}
int main(){
data a;
data b;
a.x = 0;
a.y = 0;
b.x = 1;
b.y = 1;
printf("%s %s \n", data_tostring(&a), data_tostring(&b));
return 0;
}
I expected the output was 0 0 1 1, but actually I get 0 0 0 0. Did I make a mistake with the static keyword and the returning value in data_tostring()?
Thanks for the help.
Since buffer is static, both calls to data_tostring(...) are writing to the same buffer. Furthermore, the order of evaluation of function parameters in unspecified, so there's no guarantee that data_tostring(&a) gets evaluated before data_tostring(&b).
One possible way of fixing this is by passing buffer as an argument to data_tostring:
void data_tostring(char* buffer, data* a) {
sprintf(buffer, "%f %f", a->x, a->y);
}
And then use multiple buffers in main:
int main()
{
data a;
data b;
char a_buf[255];
char b_buf[255];
a.x = 0;
a.y = 0;
b.x = 1;
b.y = 1;
// Fill buffers
data_tostring(a_buf, &a);
data_tostring(b_buf, &b);
printf("%s %s \n", a_buf, b_buf);
return 0;
}
wandbox example
If you really want to use the static buffer, you can call printf twice:
int main()
{
data a;
data b;
a.x = 0;
a.y = 0;
b.x = 1;
b.y = 1;
printf("%s", data_tostring(&a));
printf(" %s \n", data_tostring(&b));
return 0;
}
wandbox example
The problem is because in C language, the arguments in a function are evaluated from right to left.
So, first data_tostring(&b) is evaluated and the pointer points to the buffer char array.
Next, the data_tostring(&a) is evaluated and this time, the char values present already are overwritten by sprintf(buffer, "%f %f", a->x, a->y);.
So, after the two argument evaluations, the two function evaluations points to buffer char array which has the values of struct a. That's the reason you got 0 0 0 0.
Alternative solution:
Use two printf() statements and print the strings seperately or use two char buffers for each of the structs(Not recommended).
Reference: Compilers and argument order of evaluation in C++
Hope this helps.

Why can uninitialized pointer to int array be assigned variable's value?

I have read answers to questions like why a pointer can be assigned value? however I'm still a bit confused about changing the values of pointers. Some of the comments don't seem to be completely accurate, or maybe it's implementation specific. (example: a[1] is exactly the same as writing *(a + 1). Obviously you can write *a = 3 since a is int*, so you can also write *(a + 1) = 3, so you can also write a[1] = 3).
Writing *a = 3 produces a warning: initialization makes pointer from integer without a cast. As well as a segfault.
My question is as follows.
int main(void)
{
int b = 5, c = 10;
int *a = b;
*a = c; /* Will not work. (Should technically change the value of b to 10, leaving the pointer still pointing to b.) */
printf("%d\n", *a);
return 0;
}
The above example will not work, and will produce a segfault, but the following works for some reason I am not aware of.
int main(void)
{
int a[10], i;
for (i = 0; i < 10; ++i) {
*(a + i) = i; /* Supposedly the same logic as '*a = c;', but works*/
}
for (i = 0; i < 10; ++i) {
printf("%d\n", *(a + i));
}
return 0;
}
Thanks for your time and efforts.
**EDIT: Thank you for the answers, since it is *a = &b (I knew this (typo), but now the second example with the loop is unclear), the array indices are treated as variables, not as addresses I presume?
This:
int b = 5, c = 10;
int *a = b;
Doesn't work. You think the second line means this:
int *a;
*a = b;
But it doesn't. It means this:
int *a;
a = b;
The above error means that when you do this:
*a = c;
Your program crashes (or maybe not, undefined behavior!), because a is an invalid pointer (it points to address 5, which is wrong in many ways).

pointer arithmetic with pointer to array

I'm trying to do pointer arithmetic with a pointer to array, but I get a wrong value since I can't dereference the pointer properly.
Here is the code:
#include "stdlib.h"
#include "stdio.h"
int main()
{
int a[] = {10, 12, 34};
for (int i = 0; i < 3; ++i)
{
printf("%d", a[i]);
}
printf("\n");
int (*b)[3] = &a;
for (int i = 0; i < 3; ++i)
{
printf("%d", *(b++));
}
printf("\n");
return 0;
}
In the second for I can't get to print the correct value.
It doesn't work even if I write
printf("%d", *b[i]);
I'd like to see how to print correctly using the b++ and the b[i] syntax.
The following should work:
printf("%d\n", *( *b+i ));
// * b + i will give you each consecutive address starting at address of the first element a[0].
// The outer '*' will give you the value at that location.
instead of:
printf("%d", *(b++));
You have declared b to be a pointer to arrays of 3 integers and you have initialized it with address of a.
int (*b)[3] = &a;
In the first loop you will print the first element of a array but then you will move 3*sizeof(int) and trigger undefined behavior trying to print whatever there is.
To print it correctly:
int *b = a;
// int *b = &a[0]; // same thing
// int *b = (int*)&a; // same thing, &a[0] and &a both points to same address,
// though they are of different types: int* and int(*)[3]
// ...so incrementing they directly would be incorrect,
// but we take addresses as int*
for (int i = 0; i < 3; ++i)
{
printf("%d", (*b++));
}
gcc will complain about the formatting in the second for loop: it will tell you format specifies type 'int' but the argument has type 'int *
your assignment of a to b should look like this:
int *b = a

Convert a string to an integral number?

How is this even possible? One of my textbook questions (studying for an exam here) claim you can do this and ask the following:
Write a function that accepts a string. The function should convert the string to an integral number. If it cannot convert return 0.
Example 1: 8976 returns the value of
((((8*10 + 9) *10)+ 7 )* 10) + 6
Example 2: 67A returns a value of 0
How can this be done? I know you can use the atoi() function but the book wants this to be done without any functions?
Edit: Some further thinking:
int i, ans;
char number[5]="8976";
for(i=0;i<strlen(number);i++)
ans=(ans*10)+(number[i]-'0');
Would the above work?
I was writing something but in the meantime the question was basically answered, in the OP edits and further comments.
Here is the function header:
int f(const char *str)
{
The variables: v is the computed value, c is a pointer to the current character being scanned, d is the value of the current digit.
int v;
const char *c;
int d;
v = 0;
c = str;
Iteration will stop on the null terminator, when c points to 0, which is FALSE in C. Scanning is left to right.
while (*c)
{
The OP got the main idea right.
v *= 10;
d = *c - '0';
You should just test d to check that it is between 0 and 9.
if (d < 0 || d > 9)
return 0;
This solution uses pointers in place of indices.
v += d;
++c;
}
Return the result.
return v;
}
You're halfway there, your code isn't bad just missing a declaration and an if
int main()
{
int i, ans;
ans=0;
char number[5]="12";
for(i=0;i<strlen(number);i++){
if( !(number[i]>='0' && number[i]<='9') ){
ans = 0;
break;
}
ans=(ans*10)+(number[i]-'0');
}
printf("%d\n",ans);
return 0;
}
you can also check the code here:
http://cfiddle.net/cvYCYB

What's the difference between *d++ and (*d)++ in C?

as in the title, what's the difference because these two seem to get me the same results?
No they are not the same. Assume that d is a pointer to int:
int n = 0;
int* d = &n;
*d++; // d++ then *d, but d++ is applied after the statement.
(*d)++; // == n++, just add one to the place where d points to.
I think there is an example in K&R where we need to copy a c-string to another:
char* first = "hello world!";
char* second = malloc(strlen(first)+1);
....
while(*second++ = *first++)
{
// nothing goes here :)
}
The code is simple, put the character pointed by first into the character pointed by second, then increment both pointers after the expression. Of course when the last character is copied which is '\0', the expression results to false and it stops!
The increment ++ has higher operator precedence than the dereference *, so *d++ increments the pointer d to point to the next location within the array, but the result of ++ is the original pointer d, so *d returns the original element being pointed to. Conversely, (*d)++ just increments the value being pointed to.
Example:
// Case 1
int array[2] = {1, 2};
int *d = &array[0];
int x = *d++;
assert(x == 1 && d == &array[1]); // x gets the first element, d points to the second
// Case 2
int array[2] = {1, 2};
int *d = &array[0];
int x = (*d)++;
assert(x == 1 && d == &array[0] && array[0] == 2);
// array[0] gets incremented, d still points there, but x receives old value
In the official C terminology, these expressions do give you the same results, as they should. In the proper terminology, the "result" of a non-void expression is what that expression evaluates to. Both of your expressions evaluate to the initial value of *d, so not surprisingly, the results are the same.
However, an addition to a "result" every expression in C has zero or more so called "side effects". And side effects of these two expressions are completely different. The first expression increments the value of pointer 'd'. The second expression increments the value of '*d' (the pointed value).
The first increments the pointer, the second increments the value pointed to.
As an experiment, try this:
int main() {
int x = 20;
int *d = &x;
printf("d = %p\n", d);
int z = (*d)++;
printf("z = %d\n", z);
printf("d = %p\n", d);
int y = *d++;
printf("y = %d\n", y);
printf("d = %p\n", d);
}
They do return the same result, but the state change in your program is completely different.
This is easiest to understand if we just expand out the operations.
x = *d++;
// same as
x = *d;
d += 1; // remember that pointers increment by the size of the thing they point to
x = (*d)++;
// same as
x = *d;
*d += 1; // unless *d is also a pointer, this will likely really just add 1
I don't have a compiler handy.
a = (*d)++;
b = (*d);
is a==b? i don't think it is.

Resources