Reputation: 53
With this code, I am able to store strings into namesArray and print them to the screen. How is this possible if namesArray is a pointer to int?
int numNames = getMaxNames(argv[1]);
int* namesArray = malloc(numNames * sizeof(int));
int i;
for (i = 0; i< numNames; i++) {
scanf("%s", &namesArray[i]);
}
for (i = 0; i< numNames; i++) {
printf("%s\n", &namesArray[i]);
}
Upvotes: 0
Views: 65
Reputation: 597
C doesn't care what the pointer is to. If sizeof(char) is 1, and sizeof(int) is 4, then malloc(sizeof(int)) is the same as malloc(sizeof(char)*4). Note malloc returns a void * anyway. Since C doesn't really care what the pointer is to, you can always just cast buffers and it won't complain. Also note, you can do this cowboy style casting between types and C doesn't care, but it isn't really good form, and many compilers will complain about it.
so consider this code:
char* str = (char*)malloc(sizeof(char)*4);
int* intArr = (int*)malloc(sizeof(int));
//it is perfectly legal to do this:
char* intStr = (char*)intArr;
//or
printf("int char %c\n", ((char*)intArry)[2]);
//or
printf("int char %c\n, intStr[2]);
//or
printf("int char %c\n, intStr+2);
//or copy intArr into str
for (int i = 0; i < 4; i++) {str[i] = ((char*)intArr)[i];}
With that said, you should actually do this kind of stuff unless you really know how pointers work and what you are doing. Make sure you are doing it for the right reasons. Because it seems to work is not a right reason. :)
So for your code, you could "fix" it like this, but this code is still "very bad." scanf is not safe. It can easily overflow your namesArray buffer.
int numNames = getMaxNames(argv[1]);
char* namesArray = (char*)malloc(numNames * sizeof(int));
int i = 0;
for (i = 0; i< numNames; i++) {
scanf("%s", namesArray);
}
for (i = 0; i< numNames; i++) {
printf("%s\n", namesArray);
}
` OR
int numNames = getMaxNames(argv[1]);
int* namesArray = (int*)malloc(numNames * sizeof(int));
int i = 0;
for (i = 0; i< numNames; i++) {
scanf("%s", (char*)namesArray);
}
for (i = 0; i< numNames; i++) {
printf("%s\n", (char*)namesArray);
}
Upvotes: 0
Reputation: 134356
You invoke undefined behavior by writing
scanf("%s", &namesArray[i]);
where, &namesArray[i]
is of type int *
.
Quoting C11
, chapter §7.21.6.2, fscanf()
(emphasis mine)
s
Matches a sequence of non-white-space characters.286) If no l length modifier is present, the corresponding argument shall be a pointer to the initial element of a character array large enough to accept the sequence and a terminating null character, which will be added automatically.
and,
[...] Unless assignment suppression was indicated by a *, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result. If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
That said, you really ought to check the success of malloc()
before using the returned pointer.
Upvotes: 2