Sorting strings in C

I was trying to sort c-strings using qsort().
Below is the comp function.

> int comp(const void *a,const void *b)
> {const char **ia=(const char **)a; 
> const char **ib=(const char **)b; 
> return strcmp(*ia,*ib); }

In main

char *b[6];
 for(int i=0;i<6;i++)
 b[i]=new char[6];
 for(int i=0;i<6;i++)
 strcpy(b[i],"");

The qsort function works in this case
where the call given to qsort was

size_t strings_len=sizeof(b)/sizeof(char *);//since the array is of char*s
 qsort(b,strings_len,sizeof(char*),comp);

here

strings_len=sizeof(b)/sizeof(char*);

However, if in main() we have

char b[6][6];
for(int i=0;i<6;i++)
strcpy(b[i],""); 

and then we call qsort() as given above a SIGSEGV occurs.Whats the difference in the two?Isn’t b[i] a pointer to the c string?

1 Like

It is because, sizeof(b) is different in both cases (and hence, strings_len).

Case 1: char *b[6];

In this case, sizeof(b) is 24. This is because, b is an array of pointers. Each pointer takes 4 bytes and there are 6 such pointers. So, total = 4*6 = 24 bytes. So, string_len will be 24/sizeof(char *) = 6.

Case 2: char b[6][6];

In this case, sizeof(b) is 36. This is because, b is a 2D array of characters. Each character takes 1 byte and there are 6*6 = 36 such characters. So, total = 1*36 = 36 bytes. So, string_len will be 36/sizeof(char *) = 9.

Now, string_len is the number of elements in the array (which actually is 6 strings, but you get 9 for case 2). Hence, the segmentation fault.

NB: Since char * is a pointer, it is storing an address. So, it needs 4 bytes of storage. So, sizeof(char *) is always 4. (All these assuming a 32-bit gcc compiler.)

1 Like

The thing is that when you declare static 2D array <type> a[ROWS][COLUMNS] it’s not <type>** ,it’s totally different type (it’s actually <type>(*)[COLUMNS], but if it confuses you, don’t worry). The thing is even though we see this as a matrix it’s linearly laid out in memory. So size of one object of a is actually COLUMNS*sizeof(type), so if you pass a as an argument to a function you always have to specify width of one element as explained before. So size_t width argument of qsort() will be 6*sizeof(char) most likely resulting in 6. And when you dereference pointers in compare function you do it like this

int compare(const void* pa, const void* pb)
{
     char* a = (char*) pa, *b = (char*) pb;
     return strcmp(a,b);
}

because you deal with elements of your array b[6][6], which are arrays of 6 characters.

1 Like

Thanks for the answer though I had found this mistake afterwards .However,if I say that in
case 2:
we have qsort(b,6,sizeof(char*))
then also it doesn’t work.
Why?

1 Like

Thanx buddy:) This was exactly what I was looking for,the compare function.

the third parameter in qsort is “size of each element in the array”. Now, in this case, each “element” itself is a character array. So, its size will be the number of bytes taken by that array, which is 6. So, the correct way is qsort(b, 6, 6*sizeof(char *), compare); or equivalently, qsort(b, 6, sizeof(b[0]), compare);