Works great.
#include <stdio.h>
#include <stdlib.h>
int main(void){
char number[]= "a123.45", *strtod_eptr;
double num;
num=strtod(number, &strtod_eptr);
if (strtod_eptr == number){
printf("Error: no number found.\n");
}
else{ printf("%f\n", num+7);
}
return 0;
}
Does not work. Second argument in strtod() changed type.
#include <stdio.h>
#include <stdlib.h>
int main(void){
char number[]= "a123.45", **strtod_epptr;
double num;
num=strtod(number, strtod_epptr);
if (*strtod_epptr == number){
printf("Error: no number found.\n");
}
else{
printf("%f\n", num+7);
}
return 0;
}
Compiler warns about uninitialized strtod_epptr but no compile errors.
strol_test.c:7:5: warning: ‘strtod_epptr’ is used uninitialized in this function [-Wuninitialized]
Program crashes (seg fault) at the if() statement.
Compiler command (in both cases):
gcc -Wall -pedantic -o "strol_test" "strol_test.c"
Why does this happen? Why does gcc complains about uninitialized **strtod_epptr while being totaly fine with (similarily uninitialized ?) *strtod_eptr ?
And what goes wrong when dereferencing **strtod_epptr? AFAIK:
char *ptr;
...strtod(...,&ptr)
should be the same as
char **ptr;
...strtod(...,ptr)
but obviously it is not. What am I missing?
Think about memory.
When you write char *str you asked the compiler to allocate memory for a char pointer. Now when you send the address of str to a function, as &str that value inside str can be changed.
Now the other way around.
When you write char **str you asked the compiler to allocate memory for a pointer to a char pointer. That means there is NO memory allocation for the char pointer. If you dereference that pointer now, it will point to nothing meaningful.
Now, you passed str to strtod(). The function now does *str = something(). BUT that place does not exist in the memory. That bucket was not created and allocated.
In the future, always pass the ADDRESS of an already existing variable. If not, there is no variable the function can update...
strtod expects a double-pointer (pointer to pointer), because it wants to tell
the user the location where it stopped reading. So it has to change where a
pointer is pointing, thus it cannot take a (single) pointer, it has to take a
pointer to a pointer.
man strtod
#include <stdlib.h>
double strtod(const char *nptr, char **endptr);
[...]
RETURN VALUE
These functions return the converted value, if any.
If endptr is not NULL, a pointer to the character after the last character used in the conversion is stored in the location referenced
by endptr.
That means that the pointer you pass through endptr must point to a valid
char-pointer, that's why
char number[]= "a123.45", *strtod_eptr;
num=strtod(number, &strtod_eptr);
works well because &strtod_eptr returns the address of the strtod_eptr
variable, it returns a pointer to a pointer. strtod can then use the pointer
to a pointer to change where the original pointer (strtod_eptr) will
point.
Internally strtod will do something like this:
double strtod(const char *nptr, char **endptr)
{
size_t i;
double converted_value;
...
if(endptr != NULL)
{
// i is the index the character after the last
// character used in the conversion
*endptr = &(nptr[i]);
}
return converted_value;
}
When endptr points to a valid location, dereferencing it won't be a problem.
However
char number[]= "a123.45", **strtod_eptr;
num=strtod(number, strtod_eptr);
doesn't work, because strtod_eptr is an uninitialzed pointer that points
to nowhere in particular. When strtod does *endptr = &(nptr[i]), it is
trying to write a value in an undefined memory location, this is undefined behaviour and the
segfault is a manifestation of that.
This would work however:
char number[]= "a123.45", *end, **strtod_eptr;
strtod_eptr = &end;
num=strtod(number, strtod_eptr);
Because in this case strtod_eptr would point to a valid location.
Related
Purpose : My main purpose was to create a string in some kind of function , it should return an adress , by returning adress using the string in main.
But I learned char array and char pointer actually using for the same purpose.
If we suppose that's true , We have these declaration :
char *arr and char arr[10] , *(arr+9)=arr[10] isn't it?
Application 1 does not work.
Application 2 does work fine.
Application 1:
#include <stdio.h>
char *foo(char arr[]);
int main(void)
{
char example[10];
example=foo(example);
printf("%s\n",example);
return 0;
}
char *foo(char arr[])
{
arr[10]="attempt";
return arr;
}
Application 2:
#include <stdio.h>
char *foo(char*);
int main(void)
{
char *example;
example=foo(example);
printf("%s\n",example);
return 0;
}
char *foo(char* arr)
{
arr="attempt";
return arr;
}
Your code will invoke undefined behavior in both segments. ( Even though you have observed that Code 2 works, it only seems to work. In reality a failure is lurking, and can show without warning. )
Make these corrections to address that problem, and see comments for explanations:
In code 1:
//int main(void){
int main(void){//int main(void) is minimum prototype for main function.
//char example[10]; // this will invoke undefined behavior
char example[10] = {"something"}; // 'example' initialized with content,
// thus averting undefined behavior
//example=foo(example);
strcpy (example, foo(example)); // char array is not assignable using `=`
// use strcpy to transfer result of "foo"
printf("%s\n",example);
return 0;
}
char *foo(char arr[]) //note: char arr[] decays into char *arr
{
//char arr[10]="attempt"; // Error: redefinition of 'arr' with a
// different type: char[10] vs char *
arr = "attempt"; //because char [] decays into char *, 'arr' is usable as is.
return arr;
}
To answer your question in comments: Why using strcpy function [after variable example was initialized] is not a undefined behaviour.
First the definition of a C string is important to know. ( C string definition is found here. )
The variable example in its original form, i.e. initialized:
char example[10];
Can contain anything. For example:
|%|h|8|\#|d|o|-|~|*|U|?|?|?|?|
// ^end of memory for 'example`
// note that the character in example[9] == 'U', not NULL, therefore, not a C string.
This would cause the function strcpy() to fail. Initializing guarantees predictable results:
char example[10] = {"something"};//properly initialized
|s|o|m|e|t|h|i|n|g|0|?|?|?|?|
// ^end of memory for 'example`
//or
char example[10] = {0}; //also properly initialized
|0|0|0|0|0|0|0|0|0|0|?|?|?|?|
// ^end of memory for 'example`
(This would require an extra step to place proper content.):
strcpy(example, "something");
The only required adjustment to Code 2 is to initialize the pointer before using: (See the reason why pointer must be initialized here.)
char *foo(char*);
//int main(void){
int main(void){//int main(void) is minimum prototype for main function.
{
//char *example; // passing this will envoke undefined behavior
char *example = NULL;// must initialize before using
example=foo(example);
printf("%s\n",example);
return 0;
}
char *foo(char* arr)
{
arr="attempt";
return arr;
}
Both do not "work" for different reasons.
The first is undefined behavior (UB) as code attempts to assign an element outside the bounds of example[10].
arr[0]='\0'; or arr[9]='\0'; would have been OK given the value passed to foo().
Converting the address of the string literal "attempt" to a char is not good code either. A well enabled compiler will warn of this basic coding lapse. #f3rmat example
char *foo(char arr[]) {
arr[10]="attempt"; <-- UB
return arr;
}
char example[10];
example=foo(example);
The 2nd is UB because code attempted to use an uninitialized value in passing a pointer. This "works" in that the UB of passing an uninitialized pointer is often benign. Since foo() does not use this "garbage" value and the rest of good is well defined, it "works".
char *foo(char* arr) {
arr="attempt";
return arr;
}
char *example;
example=foo(example); // UB - likely a garbage value is passed to `foo()`.
printf("%s\n",example); // `example` is now pointing to `"attempt"`.
I learned char array and char pointer actually using the same purpose.
Pointers and arrays are related, yet different. Avoid the "actually using the same purpose" idea.
An array is like a row of houses on a street. A pointer is the address of a house written on a piece of paper in your hand. Houses ≠ scrap of paper. You can refer to the house by its address or even a row of houses by the first house's address, yet a house and its address are different.
I tried to compile Code '1' and got the following error:
prog.c: In function ‘main’:
prog.c:8:12: error: assignment to expression with array type
example=foo(example);
prog.c: In function ‘foo’:
prog.c:14:12: warning: assignment makes integer from pointer without a cast [-
Wint-conversion]
arr[10]="attempt\n";
^
You get error: assignment to expression with array type example=foo(example); because in your left hand side, you're using an array type, which is not assignable. Assignment operator (=) needs to have a modifiable lvalue as its left operand.
You get a warning: assignment makes integer from pointer without a cast [Wint-conversion] arr[10]="attempt\n"; because the left hand side and the right hand side in this assignment have different types.
Pointer and array are not the same.
char *arr = "attempt"
Here you're creating a string constant "attempt" and assigning its address to arr which is valid
char arr[10];
arr = "attempt";
This is invalid.
you can add elements to the array by following methods.
char arr[10] = "attempt";
char arr[10] = {'a', 't', 't', 'e', 'm', 'p', 't'};
arr[0] = 'a';
arr[1] = 't'; // and so on.
when you are passing the array as an argument to another function
arr = foo(arr);
you are passing the address of the zeroth element in the array arr[0]
Hope that helps..
Char arrays can be initialized but cannot be assigned.
char example[10]="attempt";
is valid.
But
char example[10];
example="attempt"
is not valid.
More details here
Your second example works because you pass a uninitialized pointer to a function and return an address of the string literal attempt
which will work perfectly as mentioned in the answer by chux
I have declared string and pointer ptr of int type.But to access char type through pointer we use char pointer.
But here it is working properly,only giving warning.
I have written code in Codeblocks.
Warning: assignment from incompatible pointer type [-Wincompatible-pointer- types]
char name[]="Welcome";
int *ptr;
ptr=name;
int i=0;
while(name[i]!='\0') {
printf("%c",*(ptr+i));
i++;
}
Your code has undefined behaviour, the fact that it "works" means nothing.
You are mixing types here and that's what the compiler is warning you. The
problem here is this:
ptr = name;
because you are assigning a char pointer to a int pointer, they are
incompatible because char and int have different sizes and this will be a
problem when accessing memory through the int pointer.
When you do this:
printf("%c", *(ptr+i));
you eventually accessing memory out of bounds. ptr + i is pointer arithmetic,
that means that the compiler takes the size into account. When the compiler
calculates the offset for the expression ptr + i, it calculates the offset by doing i * sizeof(int).
Depending on the length of the string, this offset will be larger than limit of the name array. So it will
dereference a pointer past the bounds of the memory, and this yields undefined behaviour.
So the code is just simply wrong, like I said, the fact that it "works" means
nothing. The code could have ended with a segfault or erasing your hard drive.
Try following code:
int main()
{
char name[]="Welcome";
char *ptr;
ptr=(char*)name;
int i=0;
while(name[i]!='\0') {
printf("%c \n",*(ptr+i));
i++;
}
return 0;
}
My question is about dereferencing a char pointer
Here is my code -
#define MAX 10
char s[80]="Hello";
int main(){
char *stackValue;
stackValue=&s;//here I assined the address of s to stackValue
if(!stackValue){
printf("No place for Value");
exit(1);
}
else{
printf("\n%s",*stackValue);//This doesn't work with * before it
printf("\n%s",stackValue);//This works properly
}
return 0;
}
In the above code I have assigned the address of S[] to stackValue and when I am printing *stackValue it doesn't work ,
But If I print only 'stackValue' That works.
When I do same thing with Integer
int main(){
int i=10, *a;
a=&i;
printf("%d",*a);//this gives the value
printf("%d",a)//this gives the address
return 0;
}
Is printing char pointer and integer pointer is different. When I use * in int value it gives the value but gives an error when I use it as a char pointer.
Help me out?
With the first code snippet:
stackValue=&s; is incorrect given s is already an array to char. If you write like that then stackValue becomes pointer to pointer to char (not pointer to char).
Fix that by changing to stackValue=s;
Also, again %s expect a pointer to char (NOT pointer to pointer to char) - that explains why this doesn't work
printf("\n%s",*stackValue); // this doesn't work
You need printf("\n%s",stackValue); instead.
With the second code snippet.
a=&i; is ok because i is a single int, NOT an array.
What you are trying to do is this:
int main(void)
{
char a_data = "Hello, this is example";
char *pa_stack[] = {a_data};
printf("We have: %s\n", *pa_stack);
}
The "%s" format specifier for printf always expects a char* argument.
so this is working and correct statement
printf("\n%s",stackValue);
and in first statement you are passing value so it will give you undefined behaviour.
Can somebody tell me why this program does not work?
int main()
{
char *num = 'h';
printf("%c", num);
return 0;
}
The error I get is:
1>c:\users\\documents\visual studio 2010\projects\sssdsdsds\sssdsdsds\sssdsdsds.cpp(4): error C2440: 'initializing' : cannot convert from 'char' to 'char *'
But if I write the code like that:
int main()
{
char num = 'h';
printf("%c", num);
return 0;
}
it's working.
char *num = 'h';
Here, the letter 'h' is a char, which you are trying to assign to a char*. The two types are not the same, so you get the problem that you see above.
This would work:
char *num = "h";
The difference is that here you're using double-quotes ("), which creates a char*.
This would also work:
char letter = 'h';
char* ptrToLetter = &letter;
You should read up on pointers in C to understand exactly what these different constructions do.
char * is a pointer to a char, not the same thing than a single char.
If you have char *, then you must initialize it with ", not with '.
And also, for the formatting representation in printf():
the %s is used for char *
the %c is only for char.
In thefirst case you declared num as a pointer to a char. In the second case, you declare it as a char. In each case, you assign a char to the variable. You can't assign a char to a pointer to a char, hence the error.
'h' = Char
"h" = Null terminated String
int main()
{
char *num = "h";
printf("%s", num); // <= here change c to s if you want to print out string
return 0;
}
this will work
As somebody just said, when you write
char *num = 'h'
The compiler gives you an error because you're trying to give to a pointer a value. Pointers, you know, are just variables that store only the memory address of another variable you defined before. However, you can access to a variable's memory address with the operator:
&
And a variable's pointer should be coerent in type with the element pointed.
For example, here is how should you define correctly a ptr:
int value = 5;
//defining a Ptr to value
int *ptr_value = &value;
//by now, ptr_value stores value's address
Anyway, you should study somewhere how this all works and how can ptrs be implemented, if you have other problems try a more specific question :)
When you are using char *h, you are declaring a pointer to a char variable. This pointer keeps the address of the variable it points to.
In simple words, as you simply declare a char variable as char num='h', then the variable num will hold the value h and so if you print it using printf("%c",num), you will get the output as h.
But, if you declare a variable as a pointer, as char *num, then it cannot actually hold any character value. I can hold only the address of some character variable.
For example look at the code below
void main()
{
char a='h';
char *b;
b=&a;
printf("%c",a);
printf("%c",b);
printf("%u",b);
}
here , we have one char variable a and one char pointer b. Now the variable a may be located somewhere in memory that we do not know. a holds the value h and &a means address of a in memory The statement b=&a will assign the memory address of a to b. Since b is declared as a pointer, It can hold the address.
The statenment printf("%c",b) will print out garbage values.
The statement printf("%u",b) will print the address of variable a in memory.
so there's difference between char num and char *num. You must first read about pointers. They are different from normal variables and must be used very carefully.
I am learning C programming and I have a simple question about pointers...
I used the following code to play around with pointers:
#include <stdio.h>
int main (int argc, const char * argv[]) {
int * c;
printf("%x\n",c);
return 0;
}
When I print the value of C, I get back a 0. However, when I print &c (i.e. printf("&x\n",&c) I get an address in memory...
Shouldn't I be getting an address in memory when printing the pointer (i.e. printf("%x\n",c)?
--- EDIT ---
#include <stdio.h>
#include <stdlib.h>
int main (int argc, const char * argv[]) {
char * a = malloc(11);
printf("String please\n");
scanf("%s",a);
printf("%s",a);
}
The question is, why does printf("%s",a) returns the string instead of the address that is stored in a?
Shouldn't I use *a to follow the pointer and then print the string?
your current program is not correct. You define variable and do not set value before first use. the initial value is not guranteed for c, but you are lucky and it is equal to 0. It means that c points to nowhere. when you print &c you print address of variable c itself. So actually both versions print address.
printf is actually quite a complex function and can be made to do all sorts of tricks by giving it the right format specifier.
In your string example:
printf("%s", a)
the "%s" tells the printf function that the following variable should be treated as a string. In C, a string is a pointer to one or more char, terminated by a char containing 0. This is a pretty common request, which is why printf supports a format specifier "%s" that triggers this relatively complex behavior. If you want to print the address contained in the string pointer you have to use the format you found earlier:
printf("%x\n",a);
which tells printf to treat the contents of a as an unsigned integer, and print it in base 16.
*a would just be the value pointed to by a, which is just a single character.
You could print the single character with
printf("%c", *a);
Having int* c; If you print value of c, you get back a value that should be interpreted as a memory address of an integer value. In you example it might be 0 or something completely different as you are not initializing c.
If you print &c you get memory address of the pointer c (stored in stack).
#include <stdio.h>
int main (int argc, const char * argv[]) {
int * c;
int a=10;
c = &a;
printf("%x\n",c);
return 0;
}
This may clarify what happens when you make the int pointer point to something in memory.