Why can you pass a char vector to the scanf as the direct address or variable?

Asked

Viewed 797 times

3

If the name of the vector or matrix is already the address of the first element, why scanf(), using the primitive types (int, char, float, double) I need to pass the address, being that when we want to read a string("%s") don’t need? And another, why when we will read strings with the scanf(), even using the &, he compiles?

  • Patrick, @Maniero’s response is correct. There are conceptual errors in my response. I think it’s more appropriate to mark his response as the right one

2 answers

7

The answer is already in the question.

If you’re using a vector you have an address, and that’s what the scanf() wait, an address where it should put the entered value. A string is a vector.

If you are using a primitive type has the value and not the address, then use the operator & to get his address and indicate scanf() where he must place the value.

When a &string is picking up the address of the variable txt which is the same value that is txt is referencing if it is a array in the stack. If allocated to heap will give problem, as can be seen in this code:

#include <stdio.h>
#include <stdlib.h>
 
int main(void) {
    char txt[10];
    printf("%p\n", txt); //endereço do array
    printf("%p\n", &txt); //é a mesma coisa, por isso funciona
    scanf("%s", &txt);
    printf("%s\n\n", txt);
    char *txt2 = malloc(10);
    printf("%p\n", txt2); //aqui pega o local de armazenamento
    printf("%p\n", &txt2); //aqui pega o endereço da variável
    scanf("%s", &txt2);
//  printf("%s", txt2);  //quebra
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

When there’s a pointer to the heap, the variable, which is in the stack, holds the value of it, the storage location is in the heap.

When you have a array in stack is already the storage location and variable refers to this location. When something expects a pointer and you pass the variable of a array is already passed the pointer to the storage location on stack. If you use the & he picks up the address of this place, which is the same thing.

It’s not that it works because it’s weak typing, it’s not affecting anything. Even if that’s why it would probably compile, but it wouldn’t work. It works because it’s the same.

Of course, the language specification doesn’t say anything about this. It’s not that it’s guaranteed to be like this, but every implementation I know has this behavior because it makes sense. The ideal is not to do since it is not in the specification of the language that is allowed, so one day some implementation may change, although unlikely.

Maybe the doubt would be because you don’t know the array is transformed into a pointer when you make some access to your variable.

Depending on compiler does not compile since he identifies that there is something wrong with what he wants to do. Even if access is allowed strictly speaking it should not use in this way. This is an extension, it is not an obligation of language.

  • But in all C books, it says that it is not necessary to put the address operator (&) in the scanf... Now bugged me! And as I said in the question, the vector name itself is already the address of the first element. In this case, it would be unnecessary to use & in the scanf, since I would already be passing the vector address. I didn’t understand....

  • And it’s really not necessary. But it’s possible to use it. It’s just not considered the right one. I edited and improved the answer. Maybe you don’t understand what is a variable.

  • @Patrickcardoso , it is necessary to use to pass the memory address where will be written the reading result. Since a vector is already a contiguous space of memory, you don’t need this & to read character vectors

  • @Jeffersonquesado this I understood, but if with vectors of characters I do not need to pass, pq with an integer vector or float, I need? Do you understand what I mean? I still can’t fully understand it.

  • @Patrickcardoso you do not read in a single scanf of an integer vector or of float. What happens is one reading of an element. For the function scanf can write this element read in the right place, it needs to know how to get there. And the pointer points to a place. He understood why for primitive atomic types this is needed?

  • @Jeffersonquesado Now I managed to understand perfectly. Thank you very much!!!!

Show 1 more comment

3


There are conceptual errors in my answer. I only noticed after the reply by @Maniero. But I couldn’t remove it, it was already marked as accepted.

So while I am not correcting/removing this response, refer to his answer to something correct and more precise.

if the name of the vector or matrix is already the address of the first element, why in the scanf, using the primitive types (int, char, float, double) I need to pass the address

Are you talking about int abc[5]; scanf("%d", &abc[0]);, right?

When you do abc, you are picking up the memory address of the first element. By doing [n], you "jump" n houses and takes the value contained in the house n.

For example:

 (intA) (intB) (intC) (intD) (intE)
 [----] [----] [----] [----] [----]
 0      1      2      3      4

If you by abc[0], you will take the value contained in intA.

At once &abc[0], you take the address that points to intA.

when we want to read a string ("%s") don’t need?

The string reading of scanf will take what was typed and put it in the past memory address. When using strings with static allocation, we have a character vector. The use is like this:

char palavra[100];
scanf("%s", palavra);

Here, each character read will be placed in the corresponding position. For example, the word "abc":

(chrA) (chrB) (chrC) (chrD) (chrE)
 [----] [----] [----] [----] [----]
 0      1      2      3      4
[a]    [b]    [c]    [\0]

The character a was at position 0 of vector palavra, b in position 1 and c at position 2. The character at position 3 is the string terminator, the null character \0.

That’s how the scanf. It fills the positions pointed out by the argument.

And another, why when we go to read strings with the scanf, even using the &, he compiles?

Because C has weak typing. A lot weak.

For example:

char palavra[100];
char *ptr;
char **endereco;

ptr = palavra;
endereco = &ptr;

palavra is a vector, a kind of "special constant pointer" in C. Already ptr is a traditional pointer in C. So the assignment ptr = palavra is respecting all types.

endereco, in turn, it’s another pointer. A pointer to a pointer. So it makes sense to assign endereco = &ptr makes sense and respects typing.

However, C cannot differentiate in time from Runtime what types of variables. And at build level C treats pointers as pointers, regardless of which type is pointed. Of course, the compiler will complain, issue alerts (warnings in English), but if you had it done that way, you know.

C doesn’t care if you shoot yourself in the foot. The language assumes that the programmer knows what he is doing, so it will offer him no security against his own mistakes. If you are making monkey, the philosophy of language accept your monkey as law.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.