Related
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char first_name[10];
char last_name[10];
printf("What is your first name? >");
scanf_s("%s\n", &first_name);
printf("What is your last name? >");
scanf_s("%s\n", &last_name);
printf("Hello and welcome %s %s!\n", first_name, last_name);
return 0;
}
If I try run this program with Ctrl+F5, I am able to enter my first name, for example alex, and then my code crashes through the rest and wants to exit?
please advise of wrong doing
thanks
What we generally wish for from posters, especially those like you who are looking for debugging help, is an output of the compiler and linker warnings and errors, if any. We also recommend compiling with high warning settings, e.g. -pedantic for gcc or /W4 in Visual Studio.
Visual Studio tells me the following:
Severity Code Description Project File Line Suppression State
Warning C6064 Missing integer argument to 'scanf_s' that corresponds to conversion specifier '2'. scanf-array C:\Users\Peter\source\repos\scanf-array\scanf-array.cpp 15
Warning C6064 Missing integer argument to 'scanf_s' that corresponds to conversion specifier '2'. scanf-array C:\Users\Peter\source\repos\scanf-array\scanf-array.cpp 18
Warning C4473 'scanf_s' : not enough arguments passed for format string scanf-array C:\Users\Peter\source\repos\scanf-array\scanf-array.cpp 15
Warning C4473 'scanf_s' : not enough arguments passed for format string scanf-array C:\Users\Peter\source\repos\scanf-array\scanf-array.cpp 18
So, apparently scanf_s expects another argument. I don't know that function, so I looked it up (emphasis by me):
Unlike scanf and wscanf, scanf_s and wscanf_s require you to specify buffer sizes for some parameters. Specify the sizes for all c, C, s, S, or string control set [] parameters. The buffer size in characters is passed as an additional parameter. It immediately follows the pointer to the buffer or variable. For example, if you're reading a string, the buffer size for that string is passed as follows:
char s[10];
scanf_s("%9s", s, (unsigned)_countof(s)); // buffer size is 10, width spec. is 9
Of course you can for a test simply write 10 as the last parameter, it's just less robust in case you change the array size (which should be a define anyway). And voila, it works.
#t.niese was, by he way, right that the address operator in front of the arrays is wrong. What the function expects is the address of a char that's at the beginning of a buffer large enough to take the input; it does not expect the address of an array. The reason is that the address of an array of 10 has the type char (*)[10] while the address of an array of 20 has the type char (*)[20]; the arrays have different, unrelated types. They cannot stand in for each other e.g. in parameter declarations.
This is different in languages like Java or C# where arrays carry runtime (as opposed to compile time) information with them and can simply be passed as "array of char, it will know how long": In C and C++ this is compile time information, baked into the type, making arrays of different lengths incompatible.
C programmers and library functions like scanf use the trick to simply (by convention) pass around the address of the first character (whose type is naturally the same for all array lengths — address of char, or maybe even void!) plus, often, an additional length parameter. memcpy works that way. This trick is supported by the language: arrays "decay" or, in standard language, are "adjusted" to a pointer to their first element in most expressions, for example when they are passed as parameters. This happens precisely to aid this "address of the first element" compatibility trick.
That said, the address of the array is of course the address of its first element; that is, (intptr_t)&first_name == (intptr_t)&first_name[0] holds, so while the type of the buffer address you passed was wrong, the address itself was correct, and since scanf doesn't care about types except for its first argument, it just used it as the address of the first char, which, in fact, it was.
Another remark on the side: Don't include \n in the format, it requires the user to press enter twice here.
use std::cin instead of scanf_s .
it shows an error : error C4996: 'scanf_s': This function or variable may be unsafe
The IO functions from C library (printf*, scanf* and friends) are pretty good-old thing. Because they are power and flexible. But the cost of this is that they should be used carefully, with deep understanding what you are doing.
The main attention should be drawn on that they are variadic. That is, types of the last parameters are fully on the programmer's responsibility. This functions family is build in such a way this variadic arguments should correspond to the (mandatory) argument of format string. To be more precise: to the format specifiers in it and theirs order.
So, you specified the %s. Let's read what is written in the manual about this conversion specifier:
matches a sequence of non-whitespace characters (a string)
If width specifier is used, matches up to width or until the first
whitespace character, whichever appears first. Always stores a null
character in addition to the characters matched (so the argument array
must have room for at least width+1 characters)
Here you can read the "array" word. So, the characters array (C-string) argument should be passed to the scanf for the %s specifier. But you passed the pointer to the array. We can say: the pointer to pointer. Because an array's variable in C contains a pointer to the first array's element. The &array expression gives an address of the array variable by itself, not the array. I.e., an address in the memory where the array variable is placed. In your example, the scanf faithfully tried to put a string you entered at the address you passed -- at the place where the first_name variable stored, not at the place where the array's bytes are placed.
So, to be short, the & operators are waste in your code.
But, even you'll remove them, your code still will have chances to crash your program. Because the first_name and last_name arrays are of 10 characters long, but user can enter more than 10 symbols. In such a case, the scanf also will try to place oversized tail beyond of the arrays' storage. Most probably, this will lead to the program crash. As you can read in the quote of the %s description, the length specifier may be used with this specifier and it should refer to the target array's length. In your example, the %9s conversion specifier may be used. The last byte of the string will be filled with 0 by the scanf, so the 10th byte is reserved for this purpose.
UPDATE:
And yes, the scanf_s versions expect two arguments for one %c, %s or %[ conversion specifier -- the usual pointer and a value of type rsize_t indicating the size of the receiving array, which may be 1 when reading with a %c into a single char.
I am new to C and have some questions about the pointer.
Question 1 What`s differences b/w the following two? Which way is better to initialize a pointer and why?
int *p=NULL;
int *p;
#include <stdio.h>
void main()
{
char *s = "hello";
printf("%p\t%p",s);
//printf("%p\t%p",&s) it will give me unpredictable result every time
//printf("%p\t%p",(void *)&s) it will be fine
//Question3: why?
}
Question 2: I try to google what is %p doing. According to my reading, it is supposed to print the pointer. It that mean it print the address of the pointer?
Question 1, these are definitions of pointer p. One initializes the pointer to NULL, another leaves it uninitialized (if it is local variable in a function, and not global variable, global variables get initialized to 0 by default). Initializing with NULL can be good, or it can be bad, because compiler can warn you about use of uninitialized variables and help you find bugs. On the other hand compiler can't detect every possible use of uninitialized variable, so initializing to NULL is pretty much guaranteed to produce segmentation fault if used, which you can then catch and debug with a debugger very easily. Personally I'd go with always initializing when variable defined, with the correct value if possible (if initialization is too complex for single statement, add a helper function to get the value).
Question 2, %p prints the address value passed to printf. So printf("%p", pointer); gets passed value of variable pointer and it prints that, while printf("%p", &pointer); (note the extra & there) gets passed address of the variable pointer, and it prints that. Exact numeric format of %p is implementation defined, it might be printed just as a plain number.
Question 3 is about undefined behavior, because format string has more items than what you actually pass to printf. Short answer is, behavior is undefined, there is no "why". Longer answer is, run the application with machine code debugger and trace the execution in disassembly view to see what actually happens, to see why. Note that results may be different on different runs, and behavior may be different under debugger and running normally, because memory may have different byte values in different runs for various reasons.
1) The first is an initialization (to NULL in this case) the second is only a declaration of p as a pointer to int, no initial value is assigned to p in this case. You should always prefer an initialization to prevent undefined behavior.
2) You should cast to void* when using %p to print out a pointer (beware that you are using it too many times in your format specifier). The memory address to which p points is printed.
1)
int *p = NULL
defines and initializes a pointer 'p' to NULL. This is the correct way to initialize pointers in order to get "Seg Fault" if you forget to assign a valid address to this pointer later.
int *p
Only defines a pointer "p" with an unknown address. If you forget to assign a valid value to this pointer before using it, then some compilers will notify you about this mistakes while some others will not and you may access a non-valid address and get a run time error or undefined behaviour of the program.
2) "%p" is printing the address where the pointer is points. Since the pointer holds an address, then "%p" prints this address.
printf("%p\t%p",s);
So the first "%p" will print the address where the pointer "s" points which is the address which stores the string "hello". However, note that you are using twice "%p" but you providing only one pointer to print its address !!
Most compilers will not scream about this cause it is effect-less; however try to avoid it.
Answer1 :
int *p=NULL;
p is a pointer to a int variable initialized with NULL. Here NULL means pointer p is not pointing to any valid memory location.
int *p;
p is a pointer to a int variable. p in uninitialized. Reading uninitialized variables is Undefined Behavior. (one possibility if try to use is that it will throw a segmentation fault)
Answer2:
It prints content of pointer. I mean base address of string "hello"
The main difference is that in *p = NULL, NULL is a pre-defined and standard 'place' where the pointer points.
Reading from Wikipedia,
The macro NULL is defined as an implementation-defined null pointer constant,
which in C99 can be portably expressed as the integer value 0
converted implicitly or explicitly to the type void*.
This means that the 'memory cell' called p contains the MACRO value of NULL.
If you just write int *p, you are naming the memory cell with the name p but this cell is empty.
I don't know why this code don't show error.
Let me know this why.
char str[10][5];
scanf("%s",&str[1]);
printf("%s",str[1]);
I think this must show error but this show only warning and normally execute.
Please tell me why this normally execute.
As discussed a few times before, the address of an array has the same numerical value as the address of its first element (which the array will decay to when passed to a function). That is, str[1] which is an array of char will decay to a pointer to char containing the same address as &str[1], which is the address of that array. And, believe it or not, the array starts with its first element so that both share the same address.
So both pointers point to some memory location inside str, that is, to valid addresses; they are typed just differently. C's weak type system tolerates the type differences. scanf will just assume from the format specifier %s that you passed a char pointer. Since the memory there is good (it's s[1] after all) you can scan into it.
Yes, it's UB but works on every platform available to mere mortals.
The values of str[1] and &str[1] are the same. But their types are not, the types are char* and char(*)[5] respectively.
The required type for %s is char*, if you pass an incompatible type, as you do, you get undefined behavior. Now since the value is the same, the program will work, but the code itself is not correct.
The value of expression
&str[1]
is equal to the value of expression
str[1]
That is the both address the same memory extent.
So you get the correct result because scanf and printf process the value according to the format specifier %s That is scanf stores characters at this memory extent appending them with terminating zero and printf outputs the characters from the same memory extent until it encounters the terminating zero. And the both expressions aboth supply the same address.
scanf and printf are functions that got variadic arguments. It means that you can pass any quantity of any arguments in it. Any faults followed by misuse of such a functions lead to undefined behaviour and therefore such functions considered unsafe.
This is the code:
void main()
{ char strvek[500];
printf("Mata in ett stort tal: ");
scanf("%s", &strvek);
size_t len1 = strlen(strvek);
printf("%d",&len1);
}
The program ends up Printing the memory adress of len1. I want to store the length of the string in len1. If "hello" is entered I want to have the integer 5 for example.
There are thee issues with your code:
scanf does take addresses, but since strvek is an array, it "decays" to a pointer when passed to a function
Users can type more characters than your buffer holds for a buffer overflow, and
printf does not need an address for ints (your code has undefined behavior)
Here is how you fix the first two problem:
scanf("%499s", strvek); // Limit the size to 499 chars + '\0'; no ampersand in front of strvec
Here is how you fix the last problem:
printf("%d", len1); // No ampersand
It may be a little hard at first to remember when to use an ampersand with I/O functions. Generally, remember that scanf needs an ampersand except for strings, and printf does not need an ampersand except the %p format specifier (in which case you need to convert the pointer to void*).
Because you are printing the address of the len1 in the output.
Simply write:
printf("%d",len1);
What people have failed to mention in other answers (so far) is the reason why scanf wants you to pass addresses of values, while printf wants you to pass the values themselves.
In some sense, there's no technical reason why printf could not have been designed to take the addresses to values to print. If that were the convention, printf would simply go look up what is at that address (using the pointer dereference operator, *)...and print it.
Two things though:
That dereference is an "extra step" which is not needed; because just having a copy of the value itself is enough to transmit the information to printf. C likes to avoid extra steps when it can.
An address-based convention would prohibit using printf on literal values, which don't have addresses. You can't write printf("Value is %d", &10); and have it print Value is 10. This could be worked around by making a variable to store the value in and passing the address of the variable... but as I just said, C likes to avoid extra steps.
Yet with scanf, there is a technical reason why an address is required, and not a value. It needs to receive a place to put the data, such that the caller can look at that data later.
Think about reading in integers, for example. If you passed in an integer value of zero (instead of the address of an integer variable) and that's all scanf had to go on...how would it ever get the value it read back to you?
(In the particular example here, with an array of characters, there is a subtle issue regarding the lack of necessity of the address operator: see How come an array's address is equal to its value in C?...but ignore that and focus on the integer example for the concept. :-P)
It shall be
char strvek[500];
[...]
scanf("%s", strvek);
Even better do
scanf("%499s", strvek);
to prevent overflowing the buffer.
When scanning in a "string", that is a char array, passing to scanf() the array itself, lets the array decay to a pointer to its 1st element, which make it unnecessary to use the & (address of) operator.
To print out a size_t typed variable do:
size_t len = ...;
printf("%zu", len1);
printf("%d",&len1) prints the address while printf("%d",len1) prints the length itself. The & operator means "address of"
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
#include <stdio.h>
int j;
int *ptr;
int main(void)
{
j = 13232323;//adress I want to assign
ptr = j;//assign the adress to the pointer
printf("%d",ptr);
}
OUTPUT:13232323
Am I doing wrong as assigning adress directly to a pointer? Pointer is nothing but a variable contains value in the address form, so I constructed an address and then assign it to the pointer,it works as it was supposed to be, except that I can not construct an address containing characters ABCDEF,so,what's the big difference between int and pointer?
EDIT:
This code means nothing but solely for testing purpose
Actually what your trying is out of your eagerness., I agree, I too often do this way.
The Very first thing is if you store 13232323 in a pointer variable, the hex value of it is OXC9E8C3., so really at the time of your assigning the pointer variable (ptr) doesnot know whether really it is a valid address or invalid address. But when you dereference this address with *ptr, then comes the problem. It tries to seek the value in the address.
Then there are 2 cases..
Really if what you assigned is a valid address , then it will return the value. (Practically impossible case)
Mostly your address will be a invalid one, hence program will crash (Segmentation fault).
So, even though your program compiles, runs, until and unless you store a valid address in ptr., ptr has no use.
Your Q: It works as it was surposed to be,except that I can not construct an
address containing characters ABCDEF,so,what's the big difference
between int and pointer? printf("%d",ptr);
I think you are asking, whatever the case, I cannot store ABCDEF, hence ptr works same as int type, so what is the difference between integer and pointer?
Here it is :
You cannot deference an integer value, where as pointer can do it.
Hence it is called as pointer :)
You are seeing only numbers because you are printing the address with %d, trying printing with %x or %p.
Atlast, do you notice the compiler warning, warning: assignment makes pointer from integer without a cast , because ptr = j; in that ptr is of int* type, and j is of int type.
you need to use %x, or you can send *ptr to the printf
printf("%d", *ptr);// if you are using this you need to know what are you pointing at, and that it will be an integer
or
printf("%x", ptr);
as the comments below says, it is always better to use %p instead of %x because %x invoke undefined behaver. also when using %p one should cast his pointer to (void *)
Your code is invalid. C language does not allow this assignment
ptr = j;
Integer values cannot be converted to pointer types without an explicit cast (constant zero being the only exception).
If the code was accepted by your compiler, it simply means that your compiler extends the language beyond its formal bounds. Many compilers do that in one way or another. However, if your compiler accepted this code without issuing a diagnostic message (a warning or an error), then your compiler is seriously broken.
In other words, the behavior of our program has very little (or nothing) to do with C language.
In C you can do most of the type conversion, even the types are totally unrelated. It may cause warning though. make sure that your type conversion make sense.
Syntactically, you are not doing anything wrong here. You can anyways, assign one pointer to another, and since they only contain addresses like the one you assigned here, this is what actually happens during the pointer assignment.
But you should never assign a random address and try to dereference it, because your program doesn't have access to a memory location unless alloted by the machine. You should request the memory from the machine using a function like malloc().
As for differences between pointers and integers, the biggest one is that you can't use a dereference operator (*) on an integer to access the value at the address it contains.
And you can construct addresses using ABCDEF by prefixing your address value with 0X or 0x to signify a hexadecimal notation.
Am I doing wrong as assigning adress directly to a pointer?
Yes, the only integer types that are supposed to work directly with pointers as you do are intptr_t and uintptr_t, if they exist. If they don't exist you are not supposed to do this at all. Even then you would have to use an explicit cast to do the conversion.
Pointer is nothing but a variable contains value in the address
form,so I constructed an adress and then assign it to the pointer,it
works as it was surposed to be,except that I can not construct an
address containing characters ABCDEF,so,what's the big difference
between int and pointer?
No, on some architectures pointers can be more complex beasts than that. Memory can e.g be segmented, so there would be one part of the pointer value that encodes the segment and another that encodes the offset in that segment. Such architectures are rare nowadays, nevertheless this is something that is still permitted by the C standard.
you need ptr to hold the address of j by doing the following
ptr = &j;
ptr hold, equal to, the address of j
and you want to print the content of whats ptr is pointing to by the following
printf("%d",*ptr);
and to get the address of ptr do the following
printf("%x",ptr);
x for the hex representation