evolon696
evolon696

Reputation: 267

am i doing this right? - C code

when i run this it says the size is 4 when it is really six. it does this here:

printf("String Size: %u\n", sizeof some_string.basic_string);

i am new to c memory allocation and never used malloc before. am i using malloc right?

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

typedef struct String String;

struct String {
  char *basic_string;
};

String String_New(char basic_string[]) {
  String temp;
  temp.basic_string = (char *) malloc(sizeof basic_string);
  strcpy(temp.basic_string, basic_string);
  return temp;
}

void String_Delete(String *string) {
  free(string->basic_string);
  string->basic_string = NULL;
}

int String_GetSize(String string) {
  int i = 0, s = 0;
  while (string.basic_string[i] != '\0') {
    i++;
    s++;
  }
return s;
}

int main(int argc, char *argv[]) {
  String some_string = String_New("hello");
  printf("String Literal: %s\n", some_string.basic_string);
  printf("String Size: %u\n", sizeof some_string.basic_string);
  printf("String Length: %d\n", String_GetSize(some_string));
  String_Delete(&some_string);

  if (some_string.basic_string == NULL) {
    return 0;
  }

  return 1;
}

Upvotes: 0

Views: 156

Answers (6)

znlyj
znlyj

Reputation: 1149

I think there is something wrong in your func String_New,when you pass basic_string to String_New, it is a pointer actually, that is char *.So, in 32bit machine, sizeof(char *) is 4

Upvotes: 0

Clifford
Clifford

Reputation: 93534

In C a "string" is not a true data type. The sizeof operator takes a data type, or an object that has "type" as an operand. In your case the object is some_string.basic_string which has type char*, and the size of a pointer on your system is 4.

The solution is to define your String structure to have a size member:

struct String {
  char *basic_string;
  size_t length ;
};

And store the size when allocated in String_New(). This would simplify and make more efficient your String_GetSize() function (which is already over complicated since s == i).

Be aware also that in String_New(), that the basic_string parameter is also a pointer (despite the "array syntax" used in its signature). I would avoid this syntax, it is misleading since in C you cannot pass an array by copy unless the array is embedded in a struct; arrays always "degrade" to pointers when passed as arguments. Moreover the caller may pass a pointer rather than an array in any case. So in most cases you will have allocated too little memory (4 bytes). You should use strlen() or the method you originally used in String_GetSize() to determine the length.

String String_New(char* basic_string) 
{
  String temp;
  temp.length = strlen( basic_string ) ;
  temp.basic_string = (char *) malloc( temp.length + 1 );

  strcpy(temp.basic_string, basic_string);
  return temp;
}

size_t String_GetSize(String string) 
{
    return string.length ;
}

Upvotes: 0

David
David

Reputation: 2272

I think you're expecting sizeof to do the same thing that strlen() does, or what your String_GetSize() does. That's not what it's intended for.

You're performing sizeof on the char* pointer, i.e. "what is the size of this char*", which is a different question from "how long is the string pointed to by this char*". On most (if not all) 32-bit platforms sizeof(char*) will in fact be 4.

Upvotes: 1

centaurian_slug
centaurian_slug

Reputation: 3399

In your helper function String_New(), you are asking for the size of the pointer as opposed to the size of the string when you say "sizeof(basic_string)", thats why you get 4 and not 6. I think what you want is this:-

String String_New(const char* basic_string) {
  String temp;
  temp.basic_string = (char *) malloc(strlen(basic_string)+1);
  strcpy(temp.basic_string, basic_string);
  return temp;
}

sizeof measures the sizes of types at compile time; your string arguments will be runtime variables.

Upvotes: 1

No, the malloc inside your String_New should use the actual run-time length of the string, e.g.

String String_New(char basic_string[]) {
  String temp;
  int length = strlen(basic_string);
  temp.basic_string =
     (char *) malloc(length+1); /* 1 more byte for terminating \0 */
  strcpy(temp.basic_string, basic_string);
  return temp;
}

but you should just use strdup e.g. temp.basic_string = strdup (basic_string);

Upvotes: 1

Martin Beckett
Martin Beckett

Reputation: 96147

char *basic_string; is a pointer to some memory, the size of the pointer (on a 32bit system) is 32bits = 4bytes. Sizeof doesn't know about the size of memory you have reserved at this address.

There is generally no way to get the size of memory reserved by malloc - although your system may have some private debugging features to do this.

Upvotes: 1

Related Questions