я делаю это правильно? - код C - PullRequest
0 голосов
/ 27 ноября 2011

когда я запускаю это, он говорит, что размер равен 4, когда действительно шесть. он делает это здесь:

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

Я новичок в распределении памяти c и никогда раньше не использовал malloc. я использую malloc правильно?

#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;
}

Ответы [ 6 ]

1 голос
/ 27 ноября 2011

Я думаю, вы ожидаете, что sizeof сделает то же самое, что делает strlen(), или то, что делает ваш String_GetSize(). Это не то, для чего он предназначен.

Вы выполняете sizeof с указателем char*, т. Е. «Каков размер этого char*», что отличается от вопроса «на какую длину указывает строка char*» , На большинстве (если не на всех) 32-битных платформах sizeof(char*) фактически будет 4.

1 голос
/ 27 ноября 2011

Нет, malloc внутри вашего String_New должно использовать фактическую длину времени выполнения строки , например,

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;
}

, но вы должны просто использовать strdupнапример, temp.basic_string = strdup (basic_string);

1 голос
/ 27 ноября 2011

В вашей вспомогательной функции String_New () вы запрашиваете размер указателя, а не размер строки, когда вы говорите «sizeof (basic_string)», поэтому вы получаете 4, а не 6. Я думаю, чтоВы хотите это: -

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 измеряет размеры типов во время компиляции;ваши строковые аргументы будут переменными времени выполнения.

1 голос
/ 27 ноября 2011

char *basic_string; - указатель на некоторую память, размер указателя (в 32-битной системе) составляет 32 бита = 4 байта. Sizeof не знает о размере памяти, который вы зарезервировали по этому адресу.

Как правило, нет способа получить размер памяти, зарезервированный malloc - хотя ваша система может иметь некоторые частные функции отладки для этого.

0 голосов
/ 27 ноября 2011

Я думаю, что-то не так в вашей функции String_New, когда вы передаете basic_string в String_New, это фактически указатель, то есть char *. Так, в 32-битной машине sizeof(char *) равен 4

0 голосов
/ 27 ноября 2011

В C «строка» не является истинным типом данных.Оператор sizeof принимает тип данных или объект, имеющий «тип» в качестве операнда.В вашем случае объект some_string.basic_string имеет тип char*, а размер указателя в вашей системе равен 4.

Решение состоит в том, чтобы определить структуру String, имеющую член размера:

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

И сохраните размер при выделении в String_New().Это упростит и повысит эффективность вашей String_GetSize() функции (которая уже слишком сложна, поскольку s == i).

Также следует помнить, что в String_New() параметр basic_string также является указателем(несмотря на «синтаксис массива», использованный в его подписи).Я хотел бы избежать этого синтаксиса, он вводит в заблуждение, поскольку в C вы не можете передать массив путем копирования, если массив не встроен в структуру;массивы всегда «ухудшаются» до указателей при передаче в качестве аргументов.Более того, вызывающая сторона может передать указатель, а не массив в любом случае.Таким образом, в большинстве случаев вам будет выделено слишком мало памяти (4 байта).Вы должны использовать strlen() или метод, который вы первоначально использовали в String_GetSize(), чтобы определить длину.

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 ;
}
...