-3

I am relatively new to C. I have encountered quite a few segmentation faults but I was able to find the error within a few minutes. However this one's got me confused. Here's a new function I was trying to write. This basically is the C equivalent of the python code

    r=t[M:N]

Here's my C code with a test case

    #include <stdio.h>

    char* subarraym(char* a, int M, int N)
    {
    char* s;
    int i;
    for (i=M; i<N; i++){ s[i-M]=a[i]; }
    return s;
    }

   main()
   {
   char* t="Aldehydes and Ketones";
   char* r=subarraym(t,2,10);
   printf("%c\n",r[4]);
   return 0;
   }

The expected answer was 'd'. However I got a segmentation fault. Extra Info: I was using GCC

  • 7
    `s` is a pointer... so what is it pointing to? – indiv Aug 11 '14 at 17:44
  • 4
    You never allocate memory for whatever `s` points to. You just create a pointer. – Filipe Gonçalves Aug 11 '14 at 17:44
  • In C, you need to either use `malloc` in the function to get non-local buffer for return value (such as POSIX `strdup` does), or you need to pass in big enough buffer as function parameter (such as when you use `strcpy`). – hyde Aug 11 '14 at 17:50
  • 2
    Use `char* s = malloc(N-M+1)`, or more generally, `type* s = malloc((N-M+1)*sizeof(type))`. – barak manos Aug 11 '14 at 17:51
  • 1
    I'd say also that a segmentation faults is a pretty usual thing. Even When you become more experienced, such a bugs just going to hide deeper. You have to learn how to find them. And you have to learn how to use a debugger, cuz this is one of a very valuable tools that could help you to find a segmentation faults. I'd recommend to use GDB, it can show to you what the source code accords to an assembly line. – Hi-Angel Aug 11 '14 at 17:52
  • Also, in C you are responsible for terminating strings with NUL char, and reserving space for it. – hyde Aug 11 '14 at 17:53
  • And finally, if you are dealing with char buffers instead of strings, and want to pass them around, then you need to keep track of the length yourself. C arrays do not know their own length at runtime, and neither does a buffer allocated with `malloc`. – hyde Aug 11 '14 at 18:02

3 Answers3

1

Your code will not work because your sub-array pointer is never initialized. You could copy the sub-array, but then you will have to manage the memory, and that's overkilling for your problem.

In C, arrays are usually passed around as pairs of pointer and number of elements. For example:

void do_something(char *p, int np);

If you follow this idiom, then getting a sub-array is trivial, assuming no overflow:

void do_something_sub(char *p, int np, int m, int n)
{
    do_array(p + m, n);
}

Checking and managing overflow is also easy, but it is left as an exercise to the reader.

Note 1: Generally, you will not write a function such as do_something_sub(), just call do_something() directly with the proper arguments.

Note 2: Some people prefer to use size_t instead of int for array sizes. size_t is an unsigned type, so you will never have negative values.

Note 3: In C, strings are just like char arrays, but the length is determined by ending them with a NUL char, instead of passing around the length. So to get a NUL-terminated substring, you have to either copy the substring to another char array or modify the original string and overwrite the next-to-last char with the NUL.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • @hyde: Hmmm, maybe... The function is named `subarraym`, not `substringm` though. I'll add a note to the answer, just in case. – rodrigo Aug 11 '14 at 17:57
0

From

...,10);

you expect to receive 10 char (+1 0-terminator), so provide it to the function somehow.

Not doing so, but writing to invalid memory by

char * s; /* note, that s is NOT initialised, so it points "nowhere". */
...
  s[i-M] = ...

provokes undefined behaviour.

Possible solution to provide memory for such a case can be found in this answer: https://stackoverflow.com/a/25230722/694576

Community
  • 1
  • 1
alk
  • 69,737
  • 10
  • 105
  • 255
0

You need to secure the necessary memory.

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

char* subarraym(char *a, int M, int N){
    if(N < 0){
        N += strlen(a);
        if(N < 0)
            N = 0;
    }
    int len = N - M;
    char *s =calloc(len+1, sizeof(char));//memory allocate for substring
    return memcpy(s, &a[M], len);
}

int main(){
    char *t="Aldehydes and Ketones";
    char *r=subarraym(t,2,10);
    printf("%c\n",r[4]);
    free(r);
    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70