Array/Pointer: Left operand must be l-value - c

I've just started out with C and I'm struggling to get to grips when mixing pointers and arrays.
I am getting the following error:
error C2106: '=' : left operand must be l-value
#include <stdio.h>
struct PersonDetails {
char *name;
int *phoneNumber;
};
int* getPhoneNumber(struct PersonDetails *phoneBook[], char* name);
int main() {
struct PersonDetails a;
struct PersonDetails b;
struct PersonDetails people[2];
struct PersonDetails *ptr[2];
char aName = 'T';
int aNum = 123;
char bName = 'O';
int bNum = 456;
a.name = &aName;
a.phoneNumber = &aNum;
b.name = &bName;
b.phoneNumber = &bNum;
people[0] = a;
people[1] = b;
ptr = &people;
printf("%d", *getPhoneNumber(ptr, aName));
return 0;
}
int* getPhoneNumber(struct PersonDetails *phoneBook[], char* name) {
int i;
for (i = 0; i < 2; i++) {
if (*phoneBook[i]->name == *name) return phoneBook[i]->phoneNumber;
}
return 0;
}
It's happening on the line:
ptr = &people;
Edited Code:
#include <stdio.h>
struct PersonDetails {
char *name;
int *phoneNumber;
};
int* getPhoneNumber(struct PersonDetails *phoneBook[], char* name);
int main() {
struct PersonDetails a;
struct PersonDetails b;
struct PersonDetails people[2];
struct PersonDetails *ptr;
char aName = 'T';
int aNum = 123;
char bName = 'O';
int bNum = 456;
a.name = &aName;
a.phoneNumber = &aNum;
b.name = &bName;
b.phoneNumber = &bNum;
people[0] = a;
people[1] = b;
ptr = people;
printf("%d", *getPhoneNumber(ptr, aName));
return 0;
}
int* getPhoneNumber(struct PersonDetails *phoneBook, char* name) {
int i;
for (i = 0; i < 2; i++) {
if (*phoneBook[i].name == *name) return phoneBook[i].phoneNumber;
}
return 0;
}

Transferring sundry comments of mine in dialogue with the OP into an answer
Because the method getPhoneNumber() requires the parameter struct PersonDetails *phoneBook[].
Why does getPhoneNumber() require that eccentric type? There must be a reason why you chose to use it (like "the teacher set that in the question I'm working on"). Otherwise, it seems more likely that the parameter should be either struct PersonDetail *who or struct PersonDetail who[] — which, in the context of a function's parameter list (and only in the context of a function's parameter list) amounts to the same thing.
Originally it was PersonDetails *phoneBook, but I didn't think that would work? Am I wrong in thinking that, and how would I go about using that to find a number using a name?
Assuming you mean struct PersonDetails *phoneBook (there isn't a type PersonDetails in your code, but there is the type struct PersonDetails), then that would work fine. It is a pointer parameter that can either point to a single person's details, or to the start of an array of people's details. Inside the function, as long as you know that the array is big enough, you can use phoneBook[i].name or phoneBook[i].number with care. (Or, indeed, phoneBook->name and phoneBook->number, which refer to the single element pointed at by phoneBook, or you can think of it as using an effective subscript of 0.)
Oh wow, thank you, that helps so much. So I would change ptr to just struct PersonDetails *ptr; as opposed to an array of pointers?
Yes — using struct PersonDetails *ptr; is all you need. You are (accidentally) delving into more complex structures which do have a place in more complex situations, which is why no-one could say "this is wrong", but they're currently beyond what you need, or what you currently understand. That's OK; what you've just learned probably covers 95% or more of real life use cases.
Okay, it all compiles now, but crashes when executed. I have a feeling it has something to do with how I'm assigning both ptr and people. Do I just delete the people array? I've added an edited section in the question if you could have a look for me please?
You are now passing a char value, aName, where the function expects a char *, which would be &aName. The function prototype at the top also doesn't match the function definition; the definition is correct. You need to remove either the * or the [] but not both from the prototype. With that, it 'works'.
Be aware that you don't have strings (the char * values do not point to null terminated arrays of characters) so you can't do string comparison (strcmp()), but fixing that is probably the next phase of development.
Your compiler should have been generating warnings; pay heed. Remember, it knows a lot more about C than you do at the moment!
Working code
#include <stdio.h>
struct PersonDetails
{
char *name;
int *phoneNumber;
};
int *getPhoneNumber(struct PersonDetails *phoneBook, char *name);
int main(void)
{
struct PersonDetails a;
struct PersonDetails b;
struct PersonDetails people[2];
struct PersonDetails *ptr;
char aName = 'T';
int aNum = 123;
char bName = 'O';
int bNum = 456;
a.name = &aName;
a.phoneNumber = &aNum;
b.name = &bName;
b.phoneNumber = &bNum;
people[0] = a;
people[1] = b;
ptr = people;
printf("%d\n", *getPhoneNumber(ptr, &aName));
return 0;
}
int *getPhoneNumber(struct PersonDetails *phoneBook, char *name)
{
int i;
for (i = 0; i < 2; i++)
{
if (*phoneBook[i].name == *name)
return phoneBook[i].phoneNumber;
}
return 0;
}
Note that printing the result directly as shown will fail horribly (usually) if the 'name' is not found. You'll be dereferencing a null pointer, which invokes undefined behaviour — A Bad Thing™! You really need to use:
int *p_number = getPhoneNumber(ptr, &name);
if (p_number == NULL)
printf("No entry for name %c\n", name);
else
printf("Number for %c is %d\n", name, *p_number);
You should also review why you have int *number; instead of just int number; or char *number;. The former is better if you simply store an unformatted integer; the latter is better if you might need to store +44 1395 276679 or something like that, though you should then consider the relative merits of char number[MAX_PHONE_NUMBER_STRING_LEN]; instead of a pointer.
Also, for more nearly general-purpose code, your function should probably be told how many entries there are in the phone-book, rather than using a hard-wired size of 2 (which is a pretty minimal phone-book by any standard):
int *getPhoneNumber(int n_entries, struct PersonDetails *phoneBook, char *name)
{
int i;
for (i = 0; i < n_entries; i++)
{
if (*phoneBook[i].name == *name)
return phoneBook[i].phoneNumber;
}
return 0;
}
Where the number of entries in the array is a parameter. Assuming you have C99 or C11, you could also sensibly write that as:
int *getPhoneNumber(int n_entries, struct PersonDetails phoneBook[n_entries], char *name)
{
for (int i = 0; i < n_entries; i++)
{
if (*phoneBook[i].name == *name)
return phoneBook[i].phoneNumber;
}
return 0;
}
In both these last samples, I've not changed the data types in the structure (even though I think they should be changed). I've also not added const qualifiers to the pointer/array or the name, even though both could legitimately be const-qualified.

struct PersonDetails *ptr[2];
ptr is an array of pointers and array itself is never a modifiable value. lvalue should be some location where you store values(like variable). So this is an error.

You define as follows -
struct PersonDetails people[2];
struct PersonDetails *ptr[2];
which means the people is a 2-element array of structs of type PersonDetails, while ptr is a 2-element array of pointers to such structs.
You can't override the address of an array, it's not just some pointer (although there are some mutual semantics), it's allocated on the stack.
If you meant each element in ptr to point to the respective people element, use a loop:
for (i = 0; i < 2; ++i)
ptr[i] = &people[i];
Also note that one of the effects of passing around all these pointers to simple variables defined in main, is that you can return a null pointer from getPhoneNumber, and pass it to printf - that would segfault

ptr is an array of pointers to struct PersonDetails, so ptr[0] and ptr[1]
are pointers to struct PersonDetails, then you can asign the address of a variable of the type struct PersonDetails to each element of ptr.
in C an array is something like a pointer (but it's not exactly the same) which points to a part of the
memory (with the size of the type of variables times the numbers of elements of the array) where you can store one or more variables of one type, so in
your example, you could see people like a pointer to struct PersonDetails, and ptr like a pointer to a pointer to struct PersonDetails.
So, with all that said, what you can do is ptr[0] = people or ptr[1] = people.

Related

Creating, returning, and casting a struct with a char pointer in C

I'm pretty bad at remembering C rules with structs. Basically, I have a struct like this:
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
Where the char* ptr will only be one character max.
In my program, I have to allocate and free memory to a fake disk (declared globally as char disk[100];) using my own functions:
char disk[100];
void disk_init() {
for(int i = 0; i < 100; ++i) {
disk[i] = memory[i] = 0;
}
}
struct Xalloc_struct* Xalloc(int size) {
// error checking
// ...
// run an algorithm to get a char* ptr back to a part of the global disk
// array, where index i is the index where content at disk[i] starts
char* ptr = &disk[i];
struct Xalloc_struct *ret = malloc(sizeof(struct Xalloc_struct));
ret->size = size;
ret->ptr = malloc(sizeof(char));
ret->ptr = ptr;
return ret;
}
int Xfree(void* ptr) {
struct Xalloc_struct* p = (struct Xalloc_struct*) ptr;
int size = p->size;
int index = *(p->ptr);
// .. more stuff here that uses the index of where p->ptr points to
free(p->ptr);
free(p);
return 0;
}
int main() {
disk_init();
struct Xalloc_struct* x = Xalloc(5);
Xfree(x);
return 0;
}
When this compiles I get quite a few errors:
error: invalid application of ‘sizeof’ to incomplete type ‘struct Xalloc_struct’
struct Xalloc_struct *ret = malloc(sizeof(struct Xalloc_struct));
^
error: dereferencing pointer to incomplete type
ret->size = size;
^
error: dereferencing pointer to incomplete type
free(x->ptr);
^
error: dereferencing pointer to incomplete type
int size = cast_ptr->size;
^
error: dereferencing pointer to incomplete type
int free_ptr = *(cast_ptr->ptr);
^
So, how should I be allocating and deallocating these structs? And how can I modify / edit what they contain?
First problem is Xalloc_struct is a type, not the name of a struct. You declared that type with this:
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
typedef is of the form typedef <type name or struct definition> <name of the type>. So you declared the type Xalloc_struct to be struct { char *ptr; int size; }.
That means you use it like any other type name: Xalloc_struct somevar = ...;.
Had you declared the struct with a name...
struct Xalloc_struct {
char* ptr;
int size;
};
Then it would be struct Xalloc_struct somevar = ...; as you have.
The rule of thumb when allocating memory for an array (and a char * is an array of characters) is you allocate sizeof(type) * number_of_items. Character arrays are terminated with a null byte, so for them you need one more character.
Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->ptr = malloc(sizeof(char) * num_characters+1);
But if you're only storing one character, there's no need for an array of characters. Just store one character.
typedef struct {
char letter;
int size;
} Xalloc_struct;
Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->letter = 'q'; /* or whatever */
But what I think you're really doing is storing a pointer to a spot in the disk array. In that case, you don't malloc at all. You just store the pointer like any other pointer.
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->ptr = &disk[i];
Then you can read that character with ret->ptr[0].
Since you didn't allocate ret->ptr do not free it! That will cause a crash because disk is in stack memory and cannot be free'd. If it were in heap memory (ie. malloc) it would probably also crash because it would try to free in the middle of an allocated block.
void Xalloc_destroy(Xalloc_struct *xa) {
free(xa);
}
Here's how I'd do it.
#include <stdio.h>
#include <stdlib.h>
char disk[100] = {0};
typedef struct {
char *ptr;
int idx;
} Disk_Handle_T;
static Disk_Handle_T* Disk_Handle_New(char *disk, int idx) {
Disk_Handle_T *dh = malloc(sizeof(Disk_Handle_T));
dh->idx = idx;
dh->ptr = &disk[idx];
return dh;
}
static void Disk_Handle_Destroy( Disk_Handle_T *dh ) {
free(dh);
}
int main() {
Disk_Handle_T *dh = Disk_Handle_New(disk, 1);
printf("%c\n", dh->ptr[0]); /* null */
disk[1] = 'c';
printf("%c\n", dh->ptr[0]); /* c */
Disk_Handle_Destroy(dh);
}
What you are attempting to accomplish is a bit bewildering, but from a syntax standpoint, your primary problems are treating a typedef as if it were a formal struct declaration, not providing index information to your Xalloc function, and allocating ret->ptr where you already have a pointer and storage in disk.
First, an aside, when you are specifying a pointer, the dereference operator '*' goes with the variable, not with the type. e.g.
Xalloc_struct *Xalloc (...)
not
Xalloc_struct* Xalloc (...)
Why? To avoid the improper appearance of declaring something with a pointer type, (where there is no pointer type just type) e.g.:
int* a, b, c;
b and c above are most certainly NOT pointer types, but by attaching the '*' to the type it appears as if you are trying to declare variables of int* (which is incorrect).
int *a, b, c;
makes it much more clear you intend to declare a pointer to type int in a and two integers b and c.
Next, in Xfree, you can, but generally do not want to, assign a pointer type as an int (storage size issues, etc.) (e.g. int index = *(p->ptr);) If you need a reference to a pointer, use a pointer. If you want the address of the pointer itself, make sure you are using a type large enough for the pointer size on your hardware.
Why are you allocating storage for ret->ptr = malloc(sizeof(char));? You already have storage in char disk[100]; You get no benefit from the allocation. Just assign the address of the element in disk to ptr (a pointer can hold a pointer without further allocation) You only need to allocate storage for ret->ptr if you intend to use the memory you allocate, such as copying a string or multiple character to the block of memory allocated to ret->ptr. ret->ptr can store the address of an element in data without further allocation. (it's unclear exactly what you intend here)
You are free to use a typedef, in fact it is good practice, but when you specify a typedef as you have, it is not equivalent to, and cannot be used, as a named struct. That is where your incomplete type issue arises.
All in all, it looks like you were trying to do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
char disk[100] = "";
Xalloc_struct *Xalloc (int size, int i) {
char *ptr = &disk[i];
Xalloc_struct *ret = malloc (sizeof *ret);
ret->size = size;
// ret->ptr = malloc (sizeof *(ret->ptr)); /* you have a pointer */
ret->ptr = ptr;
return ret;
}
int Xfree (void *ptr) {
Xalloc_struct *p = (Xalloc_struct *) ptr;
// int size = p->size; /* unused */
// int index = *(p->ptr); /* what is this ?? */
// .. more stuff here that uses the index of where p->ptr points to
// free (p->ptr);
free (p);
return 0;
}
int main (void) {
int i = 0;
Xalloc_struct *x = Xalloc (5, i++);
Xfree(x);
return 0;
}
Look at the difference in how the typedef is used and let me know if you have any questions.

error of dereferencing pointer, in struct

I tried all the solutions on the site and didn't manage to fix this problem
i got a declared struct in my header
struct _fileNew;
typedef struct _fileNew fileNew;
in my source file I defined fileNew
struct _fileNew
{
char chars[];
};
now in my main i tried printing something inside the struct
fileNew* blu;
int i;
for ( i = 0; i < 10; i++)
{
blu->chars[i] = 'b';
}
printf("%s", blu->chars);
and i got
error: dereferencing pointer to incomplete type
I ran a debug and i saw that the cahrs was filled correctly but it won't print it. and I doin something wrong in the source file while defining the fileNew.?
thanks!
You need to allocate a memory block for the structure in heap and assign its address to Your pointer.
In C every string ends with a '\0' (string terminator), so You need to add it also.
#include <stdio.h>
#include <stdlib.h>
#define MAX_FILE_SIZE 128
struct _fileNew;
typedef struct _fileNew fileNew;
struct _fileNew
{
char chars[MAX_FILE_SIZE];
};
int main()
{
fileNew *blu = malloc(sizeof *blu);
int i;
for (i = 0; i < 10; i++)
{
blu->chars[i] = 'b';
}
blu->chars[i] = '\0';
printf("%s", blu->chars);
return 0;
}
You only have a pointer that is not actually pointing to anything and need to allocate size for the char[]. In main you need to assign the pointer to point at the declared struct OR use malloc as the other answers suggest:
static fileNew blu;
fileNew *p_blu = &blu;
...
p_blu->chars[i] = 'b';

How to walk through array of Struct in c

I have a program which creates an array or struct and go through it for processing. Initially it initialize the array with the defined nyumber of elements. Then for some number of element in array, the name is assigned.
I pretend the code that is equal to my scenario which is tested in codebloc and get the similar error. The problem is described in comments.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _car {
char *name;
int year;
} Car;
char *getCarName(char *name, int var);
void processCar();
void printCars(Car car[]);
int INCREMENT = 10;
int main(void)
{
processCar();
return 0;
}
void processCar()
{
// create car array with amount of INCREMENT
Car CAR_ARRAY[INCREMENT];
int a=0;
// This function assign name for Car amount 10 less than INCREMENT
while (a<INCREMENT - 2) {
char *carName;
carName = getCarName(&carName, a);
CAR_ARRAY[a].name = malloc(strlen(carName) + 1);
strcpy(CAR_ARRAY[a].name, carName);
a++;
}
printCars(CAR_ARRAY);
}
void printCars(Car car[])
{
printf("IN Car \n");
int a = 0;
// when try to call name for car amount equals to INCREMENT program terminates.
while(a<INCREMENT) {
if (car[a].name != NULL) // checking if NULL
printf("Car Name : %d -> %s\n", a, car[a].name);
a++;
}
}
char *getCarName(char *name, int var)
{
name = "Toyota";
return name;
}
What is the right way to check the struct value on struct array whether it can be called?
EDIT
I created a hack to do this as follows.
// added these right after creating array
for (a = 0; a < INCREMENT; a++)
CAR_ARRAY[a].name = NULL;
I dont know if it is a standard way or not. pls advice.
You are checking for NULL before printing, which is a good idea, but it doesn't help you here, because your last two cars are uninitialised and likely contain garbage: The name pointer is not NULL, but doesn't point to a valid address either. Segmentation violation ensues.
You should initialise all cars, not only INCREMENT - 2. Alternatively, you could initialise your cars to zero by calling memset before your initialisation:
memset(CAR_ARRAY, 0, sizeof(Car) * INCREMENT);
As an aside, the way you deal with getCarName is rather shaky as well. At the moment, your name is a pointer to a string literal. Your local variable carName does a half-hearted double duty: You try to pass it by reference (but essentially you don't) and you also return it.
Basically, you could do this in one of two ways. The easier one here is to return a pointer. in that case, you don't have to pass any string:
char *getCarName(int var)
{
static char *names[3] = {"Toyota", "Dodge", "Peugeot"};
return names[var % 3];
}
and call it like so:
char *carName = getCarName(&carName, a);
Alternatively, you could pass a char pointer by reference, i.e. as pointer to pointer to char. In that case, you don't have to return anything:
void getCarName(char **name, int var)
{
static char* names[3] = {"Toyota", "Dodge", "Peugeot"};
*name = names[var % 3];
}
Call it like so:
char *carName;
getCarName(&carName, a);
There are other scenarios here, for example if you just pass a char pointer and have getCarName fill it, but I'll leave that for now - it would make everything even more complicated.

C -- Structs and Pointers Basic Questions

So I'm trying to learn C right now, and I have some basic struct questions I'd like to clear up:
Basically, everything centers around this snippet of code:
#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME_LEN 127
typedef struct {
char name[MAX_NAME_LEN + 1];
unsigned long sid;
} Student;
/* return the name of student s */
const char* getName (const Student* s) { // the parameter 's' is a pointer to a Student struct
return s->name; // returns the 'name' member of a Student struct
}
/* set the name of student s
If name is too long, cut off characters after the maximum number of characters allowed.
*/
void setName(Student* s, const char* name) { // 's' is a pointer to a Student struct | 'name' is a pointer to the first element of a char array (repres. a string)
char temp;
int i;
for (i = 0, temp = &name; temp != '\0'; temp++, i++) {
*((s->name) + i) = temp;
}
/* return the SID of student s */
unsigned long getStudentID(const Student* s) { // 's' is a pointer to a Student struct
return s->sid;
}
/* set the SID of student s */
void setStudentID(Student* s, unsigned long sid) { // 's' is a pointer to a Student struct | 'sid' is a 'long' representing the desired SID
s->sid = sid;
}
I've commented up the code in an attempt to solidify my understanding of pointers; I hope they're all accurate.
Also, I have another method,
Student* makeAndrew(void) {
Student s;
setName(&s, "Andrew");
setStudentID(&s, 12345678);
return &s;
}
which I'm sure is wrong in some way... I also think my setName is implemented incorrectly.
Any pointers? (no pun intended)
This is very wrong. If you insist on not using strcpy do something like this (not tested)
int iStringLength = strlen(name);
for (i = 0; i < iStringLength; i++) {
s->name[i] = name[i];
}
but make sure that the length is not longer than your array size.
This is also wrong
Student* makeAndrew(void) {
Student s;
setName(&s, "Andrew");
setStudentID(&s, 12345678);
return &s;
}
because the s object is destroyed when the function exits - it is local to the function scope and yet you return a pointer to it. So if you try to access the struct using this pointer it will not be valid as the instance no longer exists. If you want to do this you should dynamically allocate it using malloc . Alternatively do not return a pointer at all and use the alternative option of #Andrew .
In your "another method" you are locally declaring Student s, which will dynamically allocate space (usually on the stack) and you are returning that address on completion.
However, that stack-space will be released on the return, so there is no guarantee that the data is uncorrupted - in fact the likelyhood is that it will be!
Declare Student s in the call to your method, and pass the pointer to makeAndrew:
void makeAndrew(Student *s) {
setName( s, "Andrew");
setStudentID( s, 12345678);
}
...
Student s;
makeAndrew( &s );
...
Your function makeAndrew returns pointer to a local variable. It is only valid before the scope ends, so as soon as the function finishes, it will change when the memory gets overwritten - i. e. almost instantly. You would have to allocate it dynamically (using Student *s = new Student;, or if you really want to stick to pure C, Student *s = malloc (sizeof Student );, and then free it outside the function after it is not needed to avoid memory leak.
Or do it as Andrew suggested, it's less error-prone.
I would change the makeAndrew() function to just return a struct, not a pointer to a struct to correct the error with respect to returning a pointer to a temporary variable:
Student makeAndrew(void)
{
Student s;
setName(&s, "Andrew");
setStudentID(&s, 12345678);
return s;
}
Student aStudent = makeAndrew();
Your setName does have an error with respect to temp, which should be a char *, since you are incrementing it in your loop to point to another character in the input c-string. I think it was missing the null termination as well. And as you mention in your comment, there should be a check for overflow of the name char array in Student:
void setName(Student* s, const char* name) { // 's' is a pointer to a Student struct |
// 'name' is a pointer to the first element of a char array (repres. a string)
const char *temp;
int i;
for (i = 0, temp = name; *temp != '\0' && i <= MAX_NAME_LEN; temp++, i++)
{
*((s->name) + i) = *temp;
}
s->name[i] = '\0';
}
You can use strncpy to simplify setName:
void setName2(Student *s,const char *name)
{
#include <string.h>
strncpy(s->name, name,MAX_NAME_LEN);
s->name[MAX_NAME_LEN] = '\0';
}

Typedef and complex declaration in C

Related to this question.
What is wrong with the following code?
typedef char (*p)[20] ptr;
ptr myFunction () {
char sub_str[10][20];
return sub_str;
}
int main () {
ptr str;
str = myFunction();
}
Syntactically:
Change
typedef char (*p)[20] ptr;
To
typedef char (*ptr)[20];
To understand the syntax of typedef-declarations like this. Imagine you want to rename type T to type U. Declare a variable of type T named U and prefix the declaration with 'typedef'. That's all.
Semantically:
See my and other answers to your linked question. This is still undefined behavior
You're returning a pointer to memory that will not exist anymore when myFunction() returns.
The main problem is that substr is local to myFunction, and once myFunction exits it no longer exists, so the pointer you return will no longer be valid.
Secondly, you are not using typedef correctly. The proper syntax would be
typedef char (*ptr)[20];
Syntactically,typedef basically acts like a storage class specifier similar to static or extern (although the semantics are different). Basically, you figure out the declaration for an object
char (*ptr)[20]; // ptr is a pointer to a 20-element array of char
and then add the typedef to it:
typedef char (*ptr)[20];
Somehow myFunction needs to allocate memory in such a way that it isn't destroyed as soon as the function exits. Here's one option:
typedef char (*ptr)[20];
ptr myFunction(size_t count)
{
/**
* Dynamically allocate a block of N 20-element arrays of char
*/
ptr p = malloc(sizeof *ptr * count);
return p;
}
int main(void)
{
ptr str = myFunction(10);
size_t i, j;
for (i = 0; i < 10; i++)
for (j = 0; j < 20; j++)
str[i][j] = ...;
...
free(str);
return 0;
}

Resources