1

From my Previous Question :

Segmentation Fault in Bubble Sort

I fixed the problem and I got the Following code

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

void bubble_sort (void* base, 
                  size_t num, 
                  size_t width,
                  int (*compar)(const void*,const void*)){
    int i,j,k;
    unsigned char *ptr = base;
    unsigned char tmp[256];

    if(num < 2 || width == 0)
        return;

    for(i = num-1; i >= 0; i--)
    {
        for(j = 1; j <= i; j++)
        {
            k = compar((void*)(ptr + width * (j-1)), (void*)(ptr + width * j));
            if(k > 0)
            {
                memcpy(tmp, ptr + width*(j-1), width);
                memcpy(ptr + width*(j-1), ptr + width*j, width);
                memcpy(ptr + width * j, tmp, width);
            }
        }
    }
}

int compare_int(const void *a, const void *b)
{
    int *c = (int *)a;
    int *d = (int *)b;
    return *c - *d;
}

int compare_string(const void *a, const void *b)
{
    const char *c = (char *)a;
    const char *d = (char *)b;
    return strcmp(c, d);
}

Now this works perfectly with :

  1. Int, Long etc. Arrays like int a[] = {1, 3, 4, 52, 2, 3};
  2. char arrays like char a[5][20] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"};

But I want to implement it with char * arrays like:

  1. char *a[] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"}

Tried a bit and ran into segmentation fault
so need some help.

4
  • I saw your code and I was wrong do deleted answer, I will try if can answer you, Btw Good question. Commented Mar 1, 2014 at 18:52
  • take your time , if i figure things out ill answer Commented Mar 1, 2014 at 18:59
  • I reach to the point where bug present it in compare function (yet not success to rectified). Let me know if you post an answer here. Commented Mar 1, 2014 at 19:03
  • ok I posted an answer below check. Commented Mar 2, 2014 at 4:56

3 Answers 3

3

You're declaring the variable 'a' as a char pointer (string). But what you have is an array of strings.

Hence 'a' should be something like this

char *a[] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"};

Also, you should give your variables more meaningful names. In this case strings or words would be clearer.

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

1 Comment

1. the non-existent of braces was a mistake , corrected in edit 2. That was just a sample to explain what i'm talking about , i will keep that in mind Thanks though
0

First note declaration:

char *a = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"};

is incorrect it should be like:

char *a[] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"}; 

That is array of char pointers. And each index in a[i] points to an string literal.

The problem is in your comparison function. Your first two arrays are array of values whereas a[] is an array of pointers. read difference between char* str[] and char str[][] and how both stores in memory? to understand how memory organization of char* a[] is different than char[][] (a two dimension continue allocated memory organization).

What happens in compare_() functions you passes address of a[i] (but doesn't pass a[i] it self). It works find when a[i] is a values address e.g. for int[] and char[][] whereas in case of char*[] you are not passing address of value instead passing address of address of value. I think your main confusion is between passing between 2D chars array char[][] and and array of literal strings char*[].

First understand what are you passing to comparison function, suppose if you have following array then you are passing address of content x, y, z (that are &a[i]) but not x, y, z (that is a[i]).

           a      
        +--------+
 343    |        |
        | a[0]=x | 
        |        |
        +--------+
        |        |
 347    | a[1]=y |
        |        |
        +--------+
        |        |
 351    | a[2]=z |
        |        |
        |        |
        +--------+
   * you are passing &a[i]

Now look at memory organization in case of char a[5][20], due to continue memory organization value of &a[i] and a[i] are same. Check following code and its output:

#include<stdio.h>
int main(){
 char a[5][20] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"};
 int i = 0;
 for(i = 0; i < 5; i++)
    printf(
        "&a[i] = %p, a[i] = %p, *a[i] = %c, string a[i] = \"%s\"\n", 
        (void*)&a[i], // you are passingg this &a[i]
        (void*)a[i],  // compare &a[i] and a[i] address value
        *a[i], 
        a[i]
    );
 return 0;
}

Output:

$ gcc x.c -Wall -pedantic -o x
$ ./x
&a[i] = 0x7fff1dfb28b0, a[i] = 0x7fff1dfb28b0, *a[i] = j, string a[i] = "jhsa"
&a[i] = 0x7fff1dfb28c4, a[i] = 0x7fff1dfb28c4, *a[i] = a, string a[i] = "asndb"
&a[i] = 0x7fff1dfb28d8, a[i] = 0x7fff1dfb28d8, *a[i] = d, string a[i] = "drtfe"
&a[i] = 0x7fff1dfb28ec, a[i] = 0x7fff1dfb28ec, *a[i] = n, string a[i] = "nhurh"
&a[i] = 0x7fff1dfb2900, a[i] = 0x7fff1dfb2900, *a[i] = b, string a[i] = "bvhr"

Although &a[i] and a[i] are not same but value-wise same. To understand that are differences read Difference between &str and str, when str is declared as char str[10]?.

But value of &a[i] and a[i] are not same in case of char*[] Check following code: y.c (similar to above x.c) and its output:

#include<stdio.h>
int main(){
 char *a[] = {"jhsa", "asndb", "drtfe", "nhurh", "bvhr"};
 int i = 0;
 for(i = 0; i < 5; i++)
    printf("&a[i] = %p, a[i] = %p, *a[i] = %c, string a[i] = \"%s\"\n", 
        (void*)&a[i],
        (void*)a[i], 
        *a[i], 
        a[i]); 
 return 0;
}

output:

$ gcc y.c -Wall -pedantic -o y
$ ./y
&a[i] = 0x7fffa4674730, a[i] = 0x400690, *a[i] = j, string a[i] = "jhsa"
&a[i] = 0x7fffa4674738, a[i] = 0x400695, *a[i] = a, string a[i] = "asndb"
&a[i] = 0x7fffa4674740, a[i] = 0x40069b, *a[i] = d, string a[i] = "drtfe"
&a[i] = 0x7fffa4674748, a[i] = 0x4006a1, *a[i] = n, string a[i] = "nhurh"
&a[i] = 0x7fffa4674750, a[i] = 0x4006a7, *a[i] = b, string a[i] = "bvhr"

Now, notice values are different for &a[i] and a[i] (infact offset address values shows segments are different &a[i] get address space in stack whereas a[i] gets address space where string literal stores, but that is different matter).

So, in string comparison function: int compare_string() that statement return strcmp(c, d); will not work for char*[] and it should be something like return strcmp(*c, *d); (although it was working for char[][] where value of &[i] and a[i] are same first case I compiled code using -Wall and -pedantic it doesn't emits any warning so I believe no problem to use it as string address - but I am not sure too). And hence you need a separate version of compare_string_ for char*[] in which you call strcmp(*c, *d);. But now problem is function argument are cont void* and dereferencing cont is undefined behaviour. To rectify your code I removed const from every where and add a new function int compare_string_v2( void *a, void *b) for char* a[] as follows:

int compare_string_v2( void *a,  void *b)
{
    char **c = a;
    char **d = b;
    return strcmp(*c, *d);
}

just compile your code as: $ gcc code.c -Wall -pedantic -o code it should work fine. Here you can check @working instance of code

Comments

0

You can use this code, the simpler the better ! First write Isless Function in your main(), some thing like this:

static int IsLess(void* num1, void* num2)
{
   return (*(int*)num1 > *(int*)num2) ? TRUE : FALSE;
}

then use this code.

static void Swap(void* ptr1, void* ptr2, size_t _sizeof)
{
void* temp = malloc(_sizeof);
memcpy(temp,ptr2, _sizeof);
memcpy(ptr2,ptr1, _sizeof);
memcpy(ptr1,temp, _sizeof);
free(temp);
}
static void BubbleUp(int _end, void* _arr[], size_t _sizeofitem, fp _IsLess)
{ 
size_t j;
for(j = 0; j < _end; ++j)
{
    if(_IsLess((char*)_arr + j*_sizeofitem, (char*)_arr + (j+1)*_sizeofitem))
    {
        Swap((char*)_arr + j*_sizeofitem, (char*)_arr + (j+1)*_sizeofitem, _sizeofitem);
    }
}
}
void SortGen(void* _arr, size_t _sizeofitem, size_t _numOfItems, fp _IsLess)
{
int i;
if(_arr == NULL)
{
    return;
}
for(i = (int)_numOfItems -1; i >= 0; i--)
{
    BubbleUp(i, _arr, _sizeofitem, _IsLess);
}
}

Comments

Your Answer

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