0

I want to dynamically allocate an array of strings. So arr should consist of twenty pointers to the first character of each string.

For simplicity, each string is just the same, stored in base. The first for loop should now create my array, which seems to work just fine.

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

int main()
{
  int n = 20;
  char** arr = malloc( sizeof(char*) + n );

  char* base = "abcdefghijklmnopqrstuvwxyz";

  for(int i = 0; i < n; i++)
  {
    *(arr + sizeof(char*) * i) = base;
  }

  for(int i = 0; i < n; i++)
  {
    printf("%s\n", *(arr + sizeof(char*) * i));
  }
}

The seconds for loop creates a segmentation-fault during the second iteration.

4
  • 6
    sizeof(char*) + n is a problem Commented Nov 21, 2018 at 19:43
  • 2
    arr[i] is *(arr + i), not *(arr + sizeof(char*) * i). You have to use the sizeof operator only with the functions that operate on raw data via void * pointers. In the pointer arithmetic above, the size of one element is inferred from arr's type. Commented Nov 21, 2018 at 19:45
  • I hope you don't want to modify the things, your arr[0 ... 19] point to. Commented Nov 21, 2018 at 19:56
  • sizeof(char*) + n is actually a paste mistake Commented Nov 22, 2018 at 9:01

1 Answer 1

5

Issues

  1. char** arr = malloc( sizeof(char*) + n ); allocates (most likely) 24 bytes which can only store (most likely) six char *.

  2. You don't need to try offset the address (*(arr + sizeof(char*) * i) = base;) by the base type. The offset is automatically adjusted by the sizeof the base type.

The following changes must be made:

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

int main(void)
{
    int n = 20;
    char **arr = malloc(sizeof(char *) * n);

    char *base = "abcdefghijklmnopqrstuvwxyz";

    for(int i = 0; i < n; i++)
        arr[i] = base;

    for(int i = 0; i < n; i++)
        printf("%d: %s\n", i, arr[i]);

    return 0;
}

The preceding uses array notation. You can also use pointer notation if you'd like. Change arr[i] to *(arr + i).

Output

$ gcc main.c -o main.exe; ./main.exe
0: abcdefghijklmnopqrstuvwxyz
1: abcdefghijklmnopqrstuvwxyz
2: abcdefghijklmnopqrstuvwxyz
3: abcdefghijklmnopqrstuvwxyz
4: abcdefghijklmnopqrstuvwxyz
5: abcdefghijklmnopqrstuvwxyz
6: abcdefghijklmnopqrstuvwxyz
7: abcdefghijklmnopqrstuvwxyz
8: abcdefghijklmnopqrstuvwxyz
9: abcdefghijklmnopqrstuvwxyz
10: abcdefghijklmnopqrstuvwxyz
11: abcdefghijklmnopqrstuvwxyz
12: abcdefghijklmnopqrstuvwxyz
13: abcdefghijklmnopqrstuvwxyz
14: abcdefghijklmnopqrstuvwxyz
15: abcdefghijklmnopqrstuvwxyz
16: abcdefghijklmnopqrstuvwxyz
17: abcdefghijklmnopqrstuvwxyz
18: abcdefghijklmnopqrstuvwxyz
19: abcdefghijklmnopqrstuvwxyz

As recommended by Swordfish you should use the const qualifier on arr and base:

const char **arr = malloc(sizeof(char *) * n);
const char * const base = "abcdefghijklmnopqrstuvwxyz";

In this way:

  1. arr cannot change (without a warning/error) pointed to chars.
  2. Neither the address of base nor the pointed to chars can be changed (without a warning/error).

Thanks

To Tim Randall for catching a math error.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.