Problems getting the length of a string in c - c

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"

Related

Why address(&) give random variable with array?

char a[] = {'A'};
printf(This is random value %c", &a[0] );
This program invokes undefined behavior, as %c is not the correct conversion specifier for an address. Use %p, and cast the argument to (void*).
Note: In case the argument is of type char*, casting is optional, but for any other type, the casting is necessary.
You are printing the address incorrectly.
%c is for printing characters. To print an address use %p and cast the pointer argument (i.e. the address) to void-pointer. Like
printf(This is random value %p", (void*)&a[0] );
The C standard does not define what is supposed to happen for your program. So in principal anything may happen and random values could be the result. No one can tell for sure what your code wil do (without having expert level knowledge of the specific system you are using).
However, on most systems your code will take 1 byte from the pointer and print it as-if it was a character. So the (likely) reason for your "random characters" is that the address of the array is different every time you start the program. And that is exactly what many systems do...
They use "Address Space Layout Randomization". This basically means that the address of things in your program (here the array) are randomly determined during program start up. The idea is to make it harder for hackers to exploit your program.
Read more here: https://en.wikipedia.org/wiki/Address_space_layout_randomization

What is different between array String and common array in C?

#include<stdio.h>
int main()
{
char str[7];
scanf("%s",&str);
for(i=0; i<7; i++)
{
printf("%x(%d) : %c\n",&str[i], &str[i], str[i]);
}
printf("\n\n%x(%d) : %c or %s",&str, &str, str, str);
return 0;
}
I'm confused about pointer of C Array because of Array with String.
Actually I want to save each character for single line input.
It is worked but I found something strange...
The main issue is &str and &str[0] have same address value.
But str have String Value with %s..
str[0] have Char Value with %c..
I used str with %c then it has first two numbers of str's address.
What is going on in Array..?
Where is real address for Stirng value??
And how can scanf("%s",&str) distribute String to each char array space?
Input : 123456789
62fe40(6487616) : 1
62fe41(6487617) : 2
62fe42(6487618) : 3
62fe43(6487619) : 4
62fe44(6487620) : 5
62fe45(6487621) : 6
62fe46(6487622) : 7
62fe40(6487616) : # 123456789
This is result window of my code.
You are confused because the string and the array are the same thing. - In the memory there are only data (and pointers to that data)
When you allocate an integer or a buffer for a string you reserve some of this memory. Strings in c is defined as a sequence of bytes terminated by one byte with the value 0 - The length is not known. With the fix length array you have a known size to work with.
The real value to the string is the pointer to the first character.
When you print with %c it expects a char - str[0] not the pointer - When you print with %s it expects a pointer to a sequence of chars.
printf("\n\n%x(%d) : %c or %s",&str, &str, str[0], str);
What is different between array String and common array in C?
An array is a contiguous sequence of objects of one type.1
A string is a contiguous sequence of characters terminated by the first null character.2 So a string is simply an array of characters where we mark the end by putting a character with value zero. (Often, strings are temporarily held in larger arrays that have more elements after the null character.)
So every string is an array. A string is simply an array with two extra properties: Its elements are characters, and a zero marks the end.
&str and &str[0] have same address value.
&str is the address of the array. &str[0] is the address of the first element.
These are the same place in memory, because the first element starts in the same place the array does. So, when you print them or examine them, they will often appear the same. (Addresses can have different representations, the same way you might write “200” or “two hundred” or “2•102” for the same number. So the same address might sometimes look different. In most modern systems, an address is just a simple number for a place in memory, and you will not see differences. But it can happen.)
printf("%x(%d) : %c\n",&str[i], &str[i], str[i]);
This is not a correct way to print addresses. To print an address properly, convert it to void * and use %p3:
printf("%p(%p) : %c\n", (void *) &str[i], (void *) &str[i], str[i]);
printf("\n\n%x(%d) : %c or %s",&str, &str, str, str);
…
I used str with %c then it has first two numbers of str's address.
In the above printf, the third conversion specification is %c, and the corresponding argument is str. %c is intended to be used for a character,4 but you are passing it an argument that is a pointer. What may have happened here is that printf used the pointer you passed it as if it were an int. Then printf may have used a part of that int as if it were a character and printed that. So you saw part of the address shown as a character. However, it is a bit unclear when you write “it has the first two numbers of str's address”. You could show the exact output to clarify that.
Although printf may have used the pointer as if it were an int, the behavior for this is not defined by the C standard. Passing the wrong type for a printf conversion is improper, and other results can occur, including the program printing garbage or crashing.
And how can scanf("%s",&str) distribute String to each char array space?
The proper way to pass str to scanf for %s is to pass the address of the first character, &str[0]. C has a special rule for arrays like str: If an array is used in an expression other than as the operand of sizeof or the address-of operator &, it is converted to a pointer to its first element.5 So, you can use scanf("%s", str), and it will be the same as scanf("%s", &str[0]).
However, when you use scanf("%s",&str), you are passing the address of the array instead of the address of the first character. Although these are the same location, they are different types. Recall that two different types of pointers to the same address might have different representations. Because scanf does not have knowledge of the actual argument type you pass it, it must rely on the conversion specifier. %s tells scanf to expect a pointer to a character.6 Passing it a pointer to an array is improper.
C has this rule because some machines have different types of pointers, and some systems might pass different types of pointers in different ways. Nonetheless, often code that passes &str instead of str behaves as the author desired because the C implementation uses the same representation for both pointers. So scanf may actually receive the pointer value that it needs to make %s work.7
Footnotes
1 C 2018 6.2.5 20. (This means the information comes from the 2018 version of the C standard, ISO/IEC 9899, Information technology—Programming Languages—C, clause 6.2.5, paragraph 20.)
2 C 2018 7.1.1 1. Note that the terminating null character is considered to be a part of the string, although it is not counted by the strlen function.
3 C 2018 7.21.6.1 8.
4 Technically, the argument should have type int, and printf converts it to unsigned char and prints the character with that code. C 2018 7.21.6.1 8.
5 C 2018 6.3.2.1 3. A string literal used to initialize an array, as in char x[] = "Hello";, is also not converted to a pointer.
6 C 2018 7.21.6.2 12.
7 Even if a C implementation uses the same representations for different types of pointers, that does not guarantee that using one pointer type where another is required will work. When a compiler optimizes a program, it relies on the program’s author having obeyed the rules, and the optimizations may change the program in ways that would not break a program that followed the rules but that do break a program that breaks the rules.
String is only some kind of the shorthand of the zero terminated char array. So there is no difference between the string and the "normal" array.
Where is real address for Stirng value??
Arrays are not pointers and they only decay to pointers. So there is no physical space in the memory where the address of the first element of the array is stored.
The main issue is &str and &str[0] have same address value.
It is not the issue - array is the chunk of memory. So the address of this chunk is the same as the address of its first element. The types are different.

Need an explanation in which occasions we should use & with printf in C

As far as I know in c when using printf() we don't use &.Right?But in my programme, if I don't use it in the display function it gives me an error.Can someone explain this? Thank you
#include<stdio.h>
#define max 100
void enqueue();
char dequeue(void);
int front=-1,rear=-1,option;
char name[max][max],val;
void display(void);
void enqueue() {
printf("Enter the name of the paitent : ");
if(rear==max-1)
printf("Line is full");
else if (front==-1 && rear==-1)
front=rear=0;
else
rear++;
scanf("%s",&name[rear][rear]);
}
char dequeue(void) {
char val;
if(front==-1 || front >rear )
printf("Line is empty");
else
{
val=name[front];
front++;
if(front>rear)
front=rear=-1;
return val;
}
}
void display(void) {
int i;
if(front==-1|| front >rear)
printf("The queue is empty");
else
{
for(i=front; i<=rear; i++) {
printf("%s\t",&name[i][i]);
}
}
}
int main () {
printf("\n\n*******Medical Cneter********");
printf("\n\t1. Insert a paitent");
printf("\n\t2. Remove a paitent");
printf("\n\t3. Check Paitent list");
printf("\n\t4. Display");
printf("\n\t5. Exit");
do {
printf("\nEnter your option: ");
scanf("%d",&option);
switch(option)
{
case 1:
enqueue();
break;
case 2:
dequeue();
break;
// case 3:
case 4:
display();
break;
}
} while(option !=5);
}
If I don't use & the programme will crash. As far as I know in c when using printf() we don't use. But in my programme, if I don't use it in the display function it gives me an error.Can someone explain this? Thank you
To answer your question, let's review what the & operator does, and what types of values we need to pass to printf, and also, for comparison, what types of values we need to pass to scanf.
If you have a thing x, then the expression &x gives you a pointer to x. If x is an int, &x gives a pointer-to-int. If x is a char, &x gives pointer-to-char.
For example, if I write
int i;
int *ip;
ip = &i;
I have declared an int variable i, and a pointer-to-int variable ip. I have used the & operator to make a pointer to i, and I have stored that pointer-to-int in the variable ip. This is all fine.
As you may know, when you call scanf you always have to pass pointers to the variables which you want scanf to fill in for you. You can't write
scanf("%d %d", x, y); /* WRONG */
because that would pass the values of the variables x and y to scanf. But you don't want to pass values to scanf, you want scanf to read some values from the user, and transmit them back to you. In fact, you want scanf to write to your variables x and y. That's why you pass pointers to x and y, so that scanf can use the pointers to fill in your variables. So that's why you almost always see &'s on the arguments in scanf calls.
But none of those reasons applies to printf. When you call printf, you do want to pass ordinary values to it. You're not (usually) asking printf to pass any data back to you. So most of the printf format specifiers are defined as accepting ordinary values, not pointers-to-values. So that's why you hardly ever see &'s in printf calls.
Now, you might think of & as an operator that "converts things" to pointers, but that's not really a good way of thinking about it. As I said, given an object x, the expression &x constructs a pointer to x. It doesn't "convert" anything; it certainly doesn't "convert" x. It constructs a brand-new pointer value, pointing to x.
In the code you posted, it looks like you might have used & in an attempt to perform such a "conversion". You had an array name of type array-of-array-of-char, or a two-dimensional array of characters. You were trying to print a string with %s. You knew, or perhaps your compiler warned you, that %s needs a pointer-to-char, and you knew (or your compiler told you) that the expression name[i][i] gave a value of type char. Now, putting a & in front of name[i][i] did indeed get a value of type pointer-to-char, as %s requires, and it might even have seemed to work, but it's a pretty haphazard solution.
It's true that printf's %s needs a pointer-to-char, but it doesn't need just any pointer-to-char; it needs a pointer-to-char that points to a valid, null-terminated string. And that's why, even though %s needs a pointer, you still don't usually see &'s in printf calls. You could use & on a single character variable to get a pointer to that character, like this:
char c = 'x';
printf("%s", &c); /* WRONG */
But this is broken code, and won't work properly, because the pointer you get is not to a valid string, because there's no null termination.
In your code, you probably want to change the line
printf("%s\t",&name[i][i]);
to
printf("%s\t",name[i]);
name is a two-dimensional array of char, but since a string in C is an array of char, you can also think of name as being a (single dimensional) array of strings, and I think that's how you're trying to use it.
Similarly, I suspect you want to change the line
scanf("%s",&name[rear][rear]);
to
scanf("%s", name[rear]);
But before you say "I thought scanf always needed &!", remember, the rule is that scanf needs a pointer. And since name[i] is an array, you automatically get a pointer to its first element when you pass it to scanf (or in fact when you use it in any expression). (And this is also the reasoning behind printf("%s\t",name[i]).)
If you wanted to use an explicit &, what you want is a pointer to the beginning of the string array you want scanf to fill in, so I think you'd want
scanf("%s", &name[rear][0]);
instead of the expression you had.
(It looks like you were, probably accidentally, running your strings down the diagonal of the name array, instead of down the left edge. It's also curious that you declared the perfectly square array
char name[max][max];
that is, 100 strings of 100 characters each. It's not wrong, and it'll work, but it's curious, and it makes it easier to mix up the rows and the columns.)
`
I tried compiling your code and it seems I'm getting the error:
warning: assignment makes integer from pointer without a cast [-Wint-conversion]
val=name[front];
^
The reason is that name is a 2D array and you are assigning a pointer to a 1D array of chars to a char.
I think that in order to fully understand the problem one would have to understand how C deals with memory and pointers.
The '&' symbol means that you are taking the address of something (not to be confused with c++ references).
This means that if a function has an argument like the following:
void foo(char* bar);
and you want to pass your variable char var; to the function, you would have to call the function using the '&' symbol to explicitly tell the compiler that you want to pass the address of var as the parameter to the function.
foo(&var);
if you want to access the value of var inside function foo you would have to "dereference" the pointer so that the compiler understands that you want the value stored at the address you just passed to the function.
In order to dereference a pointer you use the '*' symbol.
char some_char_in_foo = *var;
I suggest reading up on pointers to clarify the matter further.
The %s conversion specifier in both printf and scanf expects it's corresponding argument to have type char *, and to point to the first character in a string.
Remember that in C, a string is a sequence of characters including a 0-valued terminator. Strings are stored in arrays of char (or wchar_t for "wide" strings).
Your name array can store max strings, each of which can be up to max-1 characters long, not counting the string terminator.
When an array expression is not the operand of the sizeof or unary & operators, or isn't a string literal used to initialize a character array in a declaration, the expression is implicitly converted ("decays") from type "array of char" to "pointer to char", and the value of the expression is the address of the first element.
name has type "max-element array of max-element array of char". This means that each name[i] has type "max-element array of char", which, if it's not the operand of & or sizeof, "decays" to type char *.
That's basically a long-winded way of saying that the expression max[i] is equivalent to &max[i][0]. So you can write your printf statement as
printf( "%s\t", name[i] );
Similarly, you can rewrite your scanf statement in the enqueue function as
scanf( "%s", name[i] );
although honestly, for user input it's safer to use fgets:
if ( fgets( name[i], sizeof name[i], stdin ) )
// successful input
else
// EOF or error on read
The & operator means "take the reference of". scanf modifies its arguments, therefore, you need to given a reference to the arguments you want modified. printf does not modify its arguments, therefore, you can pass its arguments by value, because it can do its job with a copy.
However, this is not a final rule, as the format string %p will print a pointer (i.e a reference). So printf might need a reference to a variable in some cases.
A more general rule would be this one: scanf takes its arguments by reference, printf takes its arguments by value.

Why no error shown this code in C?

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.

characters versus arrays in c

Why do 1, 2, and 3 work when 4 generates a segmentation fault? (See below.)
char c[10];
char* d;
1.
scanf("%s", &c);
printf("%s\n", &c);
2.
scanf("%s", c);
printf("%s\n", c);
3.
scanf("%s", &d);
printf("%s\n", &d);
4.
scanf("%s", d);
printf("%s\n", d);
Repeating the code in the question:
char c[10];
char* d;
1.
scanf("%s", &c);
printf("%s\n", &c);
This is likely to work as expected, but in fact the behavior is undefined.
scanf with a "%s" format requires an argument of type char*. &c is of type char (*)[10], i.e., it's a pointer to a char[10] array. It points to the same location in memory as the address of the 0th element of c, but it's of a different type. The same thing happens with the printf: the "%s" format tells it to expect a char* argument, but you're passing it a char(*)[10] argument.
Since scanf is a variadic function, there's no required type checking for arguments other than the format string. The compiler will (probably) happily pass the char (*)[10] value to scanf, assuming that it can handle it. And it probably can, on an implementation where all pointers have the same size, representation, and argument-passing mechanism. But, for example, a C compiler for an exotic architecture could easily make char* pointers bigger than pointers to larger types. Imagine a CPU whose native address points to, say, a 64-bit word; a char* pointer might be composed of a word pointer plus a byte offset.
2.
scanf("%s", c);
printf("%s\n", c);
This is better. c is an array, but in this context an array expression "decays" to a pointer to the array's first element -- which is exactly what scanf with a "%s" format requires. The same thing happens passing c to printf. (But there are still some problems; I'll get to that after the other examples.
3.
scanf("%s", &d);
printf("%s\n", &d);
Since d is a single char* argument, &d is of type char**, and again, you're passing arguments of the wrong type. If all pointers have the same representation (and the same argument-passing mechanism), and the input for the scanf is short enough, this might happen to "work". It treats the char* object as if it were an array of char. If char* is 4 bytes, and the input string is no more than 3 characters long, this will probably work -- as if you had used a char[4] and written the calls correctly. But it's extremely poor practice to store character strings directly into a pointer object, and there's a huge risk of writing past the end of the object, with unpredictable results. (Those unpredictable results include writing into memory that isn't being used for anything else, which could appear to work; such is the nature of undefined behavior.)
(The C standard gives special permission to treat any object as an array of characters, but in this case it's a very bad idea.)
4.
scanf("%s", d);
printf("%s\n", d);
Here the types are all correct, but unless you've initialized d to point to a sufficiently large array of char, it's likely to fail spectacularly (or, worse, appear to work "correctly", which means you've got a subtle bug that will probably show up later).
And now we get to what I mentioned above about other problems.
For example 4, I mentioned that d needs to point to a "sufficiently large" array. How large is "sufficiently large"? There's no answer to that. scanf("%s", ...) reads a whitespace-delimited sequence of characters with no upper bound on its length. If I run your program and hold down the x key, for example, I can provide an input string longer than any buffer you've provided, with unpredictable results (undefined behavior again).
The scanf function's "%s" format cannot be used safely (unless your program runs in an environment where you can control what will appear on the standard input stream).
One good way to read text input is to use fgets to read a line at a time, then use other functions to analyze the result. fgets requires you to specify the maximum length of the input; if the actual input exceeds the limit, it's truncated and left to be read by later calls. It's not quite as convenient as scanf, but it can be done safely. (And never use the gets function; like scanf("%s", ...), it cannot be used safely.)
Suggested reading:
Section 6 of the comp.lang.c FAQ does an excellent job of explaining C arrays and pointers, and how they're related (and not related). Section 12 discusses C standard I/O.
(I'm sorry this answer is so long; I didn't have time to make it shorter.)
You got undefined behavior in cases 3 and 4.
Cases one and two are the same, as both pointing to the first element in the array.
Case 3 is undefined, as you give a pointer to pointer to char when expecting pointer to char.
Case 4 is undefined, as the pointer d is not initialized.
3 works (on many platforms, and with a warning if you turn those on; technically it is undefined behavior) because you're abusing the pointer (treating &d, which is of type (char **), as (char *) and storing characters inside the memory intended for a pointer). 4 dies because the uninitialized pointer points to a random address.
The important question here is whether there is space in which to store the result.
scanf("%s", &c);
printf("%s\n", &c);
Is there storage? Yes, the address you take is that of the first element of the array. The array exists, so you can put the result there.
scanf("%s", c);
printf("%s\n", c);
Is there storage? Yes. Used like this, the array collapses into a pointer, which is passed same as above.
scanf("%s", &d);
printf("%s\n", &d);
Is there storage? Yes. It's not of the appropriate type, (char **, should be char *), but it shouldn't be any different than casting a char into a pointer type and storing it in a variable declared as a pointer. (Other answers say this is undefined behavior. I don't think it is, casting a char or any other integer type to a char * or other pointer type is well-defined, if ill-advised; show me where the standard says this is undefined.)
scanf("%s", d);
printf("%s\n", d);
Is there storage? Not that you've allocated. It could technically be the case that whatever happens to be in d points to a place in memory that won't segfault. Even if it does, it's not your memory and you could be overwriting something important, or it could change unexpectedly. You haven't told d where to find valid memory to point to, so you're playing pointer Russian roulette.

Resources