0

I am making a program to allocate a 20x20 array of characters. Here is what I did:

#include<stdio.h>
#include<stdlib.h>
int main()
{
char *a=(char*) calloc(20,sizeof(char[20]));
a[0]="abcd";
printf("%s\n",a[0]);
return 0;
}

Link to ideone.

The output of the above code is (null). Can anybody please explain this? According to me, I am allocating a pointer a 20 spaces of size 20 each. So a[0] technically has enough memory to store "abcd", yet the output is null.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
Dref D
  • 257
  • 2
  • 17

1 Answers1

2

The type of variable a that you have is incorrect: it should be char (*a)[20] (yes, with parentheses).

This line is also incorrect:

a[0]="abcd";

you cannot assign C strings like that, because a[0] is not a pointer: it is an array of 20 characters, so you need to use strcpy instead:

#include<stdio.h>
#include<stdlib.h>
int main()
{
    char (*a)[20]=calloc(20, sizeof(char[20]));
    strcpy(a[0], "abcd");
    strcpy(a[1], "wxyz");
    printf("%s\n",a[0]);
    printf("%s\n",a[1]);
    return 0;
}

See the corrected program running here.

Note: Unlike C++, C does not require type casting of void pointers. It is typical for C programs to omit the cast of results returned from malloc, calloc, and realloc, because the type is already known from the type of the variable being assigned.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • No. Don't use strcpy. ever. Use std::string. At the very worst, use strncpy. – SecurityMatt Apr 04 '13 at 17:54
  • `strncpy(from, destination, count)` is better than `strcpy(from, destination)` to prevent buffer overflow – Kevin Meredith Apr 04 '13 at 17:54
  • @SecurityMatt `std::string` is C++, this question is tagged as `C`. – Sergey Kalinichenko Apr 04 '13 at 17:57
  • @dasblinkenlight: Then use strncpy. That's why I listed both. strcpy is always a bad choice, whether you're in C or C++. – SecurityMatt Apr 04 '13 at 18:00
  • @Kevin `strncpy` is one of the most misunderstood functions in the C library. It is designed for using with strings of fixed length, not for preventing overruns. – Sergey Kalinichenko Apr 04 '13 at 18:00
  • @SecurityMatt See my comment addressed to Kevin: `strncpy` is not for preventing memory overruns, it's for working with strings of fixed length. – Sergey Kalinichenko Apr 04 '13 at 18:01
  • I was trying to implement this as something related to vector< vector > , like I did in graphs, that is allocating a array of char pointers storing pointers to an array of chars , so I modified my code http://ideone.com/gNdIXo , and it works fine. – Dref D Apr 04 '13 at 18:02
  • @DrefD It's still incorrect: if you need an array of pointers, it would look like [this](http://ideone.com/5BQKeM). Currently, you allocate more memory than you need - 20 bytes per pointer, instead of `sizeof(char*)` per pointer. – Sergey Kalinichenko Apr 04 '13 at 18:07
  • @dasblinkenlight , well the purpose of my question was not exactly for memory allocation , but to instead look for another way of declaring a 2D array of chars. Since the usual method: char**a= calloc(m,sizeof(char*); for(i=0;i – Dref D Apr 04 '13 at 18:09
  • @DrefD Allocating a 2D array would look like [this](http://ideone.com/0yzclE). Since it's a 2D array of chars, not a 1D array of pointers, you're back to `strcpy` land. – Sergey Kalinichenko Apr 04 '13 at 18:14
  • Yes, this is what I was looking for an adjacency matrix representation! Thanks @dasblinkenlight , but you mentioned typecasting not being necessary in C, can you please throw some light on this ! – Dref D Apr 04 '13 at 18:19
  • @DrefD Please see the edit to the answer. Now that I understand what you are trying to do, it's much easier to explain what's wrong. – Sergey Kalinichenko Apr 04 '13 at 18:24
  • @dasblinkenlight: WTF are you talking about? strncpy is exactly for preventing buffer overruns. That's why strcpy is not suitable for secure development, but strncpy is. http://stackoverflow.com/questions/1258550/why-should-you-use-strncpy-instead-of-strcpy. Why it was introduced is irrelevant. The fact is that strncpy's primary use today is to prevent buffer overruns. – SecurityMatt Apr 04 '13 at 18:30
  • @dasblinkenlight Based on this `OWASP` post - `https://www.owasp.org/index.php/Reviewing_Code_for_Buffer_Overruns_and_Overflows`, why doesn't `strncpy()` guard against buffer overflows? – Kevin Meredith Apr 04 '13 at 18:31
  • @SecurityMatt There is a broad confusion about the purpose of `strncpy`. I don't think I can explain it better than AndreyT did in [this answer](http://stackoverflow.com/a/2115015/335858), though. – Sergey Kalinichenko Apr 04 '13 at 18:34
  • 1
    @Kevin See the link to an answer in my comment above. Long story short, `strncpy` does not guard against buffer overflows because it does not null-terminate strings which are longer than the desired length. You need to add `str[len-1]='\0'`, the way the OWASP people did in their example. This is error-prone. That's why there's `strlcpy` function fits in. – Sergey Kalinichenko Apr 04 '13 at 18:40