0

I am writing a C program to understand strings and pointers. Everything works except the sizeof operation for a char* [] and char**[].

Here is my code:

int main(){
  puts("");
  char src[]= "rabbit";
  char* src2[] = {"rabbit","dog","monkey"};
  char* src3[] = {"fish","horse","dolphin"};
  char** src4[] = {src2,src3};
  int i,j;

  printf("Size of the char array only is %d\n",sizeof(src));
  printf("Size of the array of string pointers only is %d\n", sizeof(&src2));
  printf("Size of the array of pointers to string pointers only %d\n\n", sizeof(src4));

   puts("Single char array is:");
   for(i = 0; i<sizeof(src)-1; i++){
     printf("%c,",src[i]);
   }

  puts ("\n");

  puts("Array of strings:");
  puts(src2[0]);
  puts(src2[1]);
  puts(src2[2]);
  puts("");

  puts("Printing the char** [] contents ");

  for(i=0; i<2; i++){
    for(j=0; j < 3;j++){
      puts(src4[i][j]);
     }
  }

  puts("");

  return 0;

}

So how do get the number of elements in char* [] and char** [] ? Also on another note if I for example declare char*[] src2 = {"rabbit","dog","monkey"}; as only char*[] m_src. Then do I have to malloc space for each element I add into this array ? for example

If I had instead done

    // Code segment changed for char*[]
    char* m_src[];
    // could I do this
    m_src = malloc(3 * sizeof(char*));
    m_src[0] = "rabbit";
    m_src[1] = "dog";
    m_src[2] = "monkey";

    /* Even more is there a way to dynamically add elements to the
    array like mallocing space for a single element at a time and tacking it onto the
    array char* m_src? */  
SeahawksRdaBest
  • 868
  • 5
  • 17
  • You can't do `char* m_src[]`; . Either do intialization at the first place, else you will need to mention the number of elements of the array. Or, `char **m_src;` and do dynamic allocation later. – smRaj Nov 03 '13 at 05:16
  • Use `%zu`, not `%d` to print a `size_t` value such as the result of `sizeof`. If your implementation doesn't support `%zu`, use `%lu` and cast the value to `unsigned long`: `printf("sizeof foo = %lu\n", (unsigned long)sizeof foo);` – Keith Thompson Nov 03 '13 at 07:13

3 Answers3

2

How do I get the number of elements in char *[] and char **[] ?

printf("Number of elements in char* src2[]: %d\n", (sizeof src2)/(sizeof src2[0]) );

Same technique for char **[] too,

printf("Number of elements in char** src4[]: %d\n", (sizeof src4)/(sizeof src4[0]) );

How do I alloc dynamic Array to point to C-style-strings ?

char **d_alloc;
d_alloc = malloc(3 * sizeof *d_alloc);
if(d_alloc == NULL)
{
    printf("malloc failed !");
    return -1; 
}
d_alloc[0] = "Created";
d_alloc[1] = "Dynamic";
d_alloc[2] = "Arrays";
printf("%s %s %s\n",d_alloc[0], d_alloc[1], d_alloc[2]);

Why the below code doesn't work ?

char** src5;
src5 = malloc(3 * sizeof(src5)); 
puts("Dynamically allotted char*"); 
src5[0] = "lion"; 
src5[1] = "shark"; 
printf("%s %s\n",src5[0],src[1]);

You wanted to dynamically allocate space for char *. So, pass malloc() the sizeof *src5 and not the sizeof src5. src5 is the pointer to char *'s , you will use later to access the dynamically allocated space.

src5 = malloc(3 * sizeof *src5); 

*src5 is of type char *.

smRaj
  • 1,246
  • 1
  • 9
  • 13
  • I wrote something similar like: ' char** src5; src5 = malloc(3 * sizeof(*src5)); puts("Dynamically allotted char**"); src5[0] = "lion"; src5[1] = "shark"; printf("%s %s\n",src5[0],src[1]);' this segfaults if I try to print more than 1 element. Any ideas why ? if I try to print the elements individually it works? – SeahawksRdaBest Nov 03 '13 at 06:27
  • @SeahawksRdaBest: Answer updated to answer the query you posted as a comment. – smRaj Nov 03 '13 at 06:58
2

sizeof is only working that way because you're creating a static string, assigning it at creation.

sizeof will show the size of the data type normally (if you use the pointer method), even after you malloc() the memory. Execute this code to demonstrate:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ()
{
        char *string;
        char *dynamic;
        dynamic = malloc(10 * sizeof(*dynamic));
        if (!dynamic)
            /* Error, malloc() failed. */
            return 1;

        /* Copy something into the string. */
        strcpy(dynamic, "testing");

        printf("sizeof char pointer:     %d\n", sizeof(string));
        printf("sizeof char:             %d\n", sizeof(*string));
        printf("dynamic:                 %s\n", dynamic);
        printf("sizeof dynamic pointer:  %d\n", sizeof(dynamic));
        printf("sizeof dynamic:          %d\n", sizeof(*dynamic));

        free(dynamic);
        return 0;
}

For your string lengths, you're probably after strlen(). When you malloc you also need to check whether it returns NULL (if it fails) and also free later. The size is usually a buffer, so to store 50 char in something you're allocating with malloc, you'd use something like this (though the sizeof part isn't needed for char):

char *str;
str = malloc(50 * sizeof(*str));
Leigh
  • 12,038
  • 4
  • 28
  • 36
  • `src2` is array of pointer-to-char. Believe he was looking for ways to dynamically allocate pointer-to-char and not `char`. `malloc(10 * sizeof(*dynamic)` will only do dynamic alloc of `char`'s – smRaj Nov 03 '13 at 05:12
  • 1
    Also, you can modify your `strcpy()` to `strncpy(dynamic, "testing", 9)`. As you have allocated only 10 `char`'s to be pointed to by `dynamic`. **[Why you should do this?](http://stackoverflow.com/questions/1258550/why-should-you-use-strncpy-instead-of-strcpy)** – smRaj Nov 03 '13 at 05:22
  • `strncpy()` has its own problems, you have to make sure you choose the length carefully. If it's a string literal with a length less than the buffer, `strcpy` is acceptable. See: http://stackoverflow.com/a/870135/2441252 – Leigh Nov 03 '13 at 05:36
  • How about `memset(dynamic, '\0', 10);` followed by `strncpy(dynamic, "testing", 9);` followed by `dynamic[9]='\0';` ? The link you posted details out problems with `strncpy()` which can be worked out. Can you justify how `strcpy()` is better than `strncpy()` ? – smRaj Nov 03 '13 at 06:21
  • I didn't say better, it's just acceptable in certain circumstances. Like when you know that a literal string that you're hardcoding is shorter in length than the buffer. – Leigh Nov 03 '13 at 06:52
2

You'll need to divide the size of the array, in bytes, by the size of a single element:

int size = sizeof(src3) / sizeof(*src3);
int size = sizeof(src4) / sizeof(*src4);
anomaaly
  • 833
  • 4
  • 15