LINUX.ORG.RU

Запутался в указателях на указатели

 ,


0

3

0) Выходные, чо ))

1) Возможно то, чего я хочу уже есть, а я и не знаю. Поэтому опишу задачу.

Хочу ф-цию которая:

char *x;
fn(&x, "abcde", 2);
printf("X: %s\n", x); // X: ab

2) Даже если такая есть, всеравно хочу понять как оно работает. Поэтому пишу свою.

void
fn(char **dst, const char *src, const size_t len)
{
    size_t src_len = strlen(src);
    size_t dst_len = (len >= src_len ? src_len : len);
    *dst = (char *) malloc(dst_len + 1);
    // часть закомментирована, падает на **dst++
    while (dst_len-- /*&& (**dst++ = *src++)*/);
    // так работает
    *dst = "ljhg";
    // еще ж в конец *dst надо '\0' воткнуть
}

ЧЯДНТ?

Ответ на: комментарий от Eddy_Em

Допустим. И как теперь туда в конец *dst '\0' воткнуть?

deep-purple ★★★★★
() автор топика

Пишу без проверки, компилятора под оффтопиком нема.

void fn(char **dst, const char *src, size_t len)
{
    size_t src_len = strlen(src);
    size_t dst_len = (len >= src_len ? src_len : len);
    *dst = (char *) malloc(dst_len + 1);
	memcpy(*dst, src, dst_len);
	(*dst)[dst_len] = 0;
}
Deleted
()
cat aa.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *fn(char **dst, const char *src, size_t len){
	size_t srclen = strlen(src);
	if(len > srclen) len = srclen;
	if(!(*dst = malloc(len+1))) return NULL;
	(*dst)[len] = 0;
	return memcpy(*dst, src, len);
}

int main(){
	char *x;
	if(!fn(&x, "abcde", 2)) return -1;
	printf("X: %s\n", x);
	return 0;
}

gcc aa.c -Wall -Werror -Wextra -o test && ./test
X: ab
Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от deep-purple
size_t dst_len = 0;
if(len >= src_len)
{
   dst_len = src_len;
}else
{
    dst_len = len;
}
size_t lowBoundDstLen = dst_len - 1;
while(lowBoundDstLen > 0)
//ну и так далее
LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от Deleted

Я знаю, что нет нужды в такой проверке, но на всякий пожарный лучше делать. Мало ли, вдруг будет архитектура, на которой эта проверка будет иметь смысл?

Eddy_Em ☆☆☆☆☆
()
pinkbyte@phantom ~/dev $ cat 1.c 
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int fn(char **dst, char* src, int len) {
        if (len<0)
                return -1;
        *dst=malloc(len+1);
        strncpy(*dst,src,len);
}

int main() {
        char *x;
        fn(&x, "abcde", 2);
        printf("%s\n",x);
        return 0;
}
pinkbyte@phantom ~/dev $ gcc 1.c 
pinkbyte@phantom ~/dev $ ./a.out 
ab

Говнокод, набросанный меньше чем за минуту. Почему говнокод? Потому что выделять память по хорошему надо не в fn, а передавать уже готовый буфер, во избежании утечек при неаккуратном использовании. Ну и проверка результата работы malloc тоже отсутствует - не есть гуд. Однако переписывать мне влом, общий смысл посыла до тебя я думаю дойдет...

Зачем тебе городить огород при наличии стандартной функции копирования строк - я решительно не понимаю

Pinkbyte ★★★★★
()
Последнее исправление: Pinkbyte (всего исправлений: 2)
Ответ на: комментарий от Pinkbyte

Зачем тебе городить огород при наличии стандартной функции копирования строк - я решительно не понимаю

Я так понял, ТС хочет делать «strdup() длиной не более len байт», но не знает, как это выразить.

Deleted
()
Ответ на: комментарий от deep-purple

всеравно хочу понять как оно работает

Лучший способ понять, как работает готовая функция при наличии сырцов - открыть ее сырцы и выкурить их

Pinkbyte ★★★★★
()
Ответ на: комментарий от Deleted

хочет делать «strdup()

Точнее strndup:

char *
strndup (const char *s, size_t n)
{
  char *result;
  size_t len = strlen (s);

  if (n < len)
    len = n;

  result = (char *) malloc (len + 1);
  if (!result)
    return 0;

  result[len] = '\0';
  return (char *) memcpy (result, s, len);
}

deep-purple ★★★★★
() автор топика

while (dst_len-- /*&& (**dst++ = *src++)*/);

В оригинале порядок операций нарушен у тебя. ++ отрабатывает до первого разыменования, по тому и падает. По идее так должно работать, но я не проверял.

while (dst_len-- && (*(*dst)++ = *src++));
Ivan_qrt ★★★★★
()
Ответ на: комментарий от Eddy_Em

Не волнуйся, на такой архитектуре это говно а) не запуститься, б) упадёт ещё быстрее по сотне других причин.

anonymous
()
Ответ на: комментарий от anonymous

а) не запуститься, б) упадёт ещё быстрее по сотне других причин

Ага [sarcasm], как и оригинальный strndup сорс которого я скинул парой постов выше ))

deep-purple ★★★★★
() автор топика
Последнее исправление: deep-purple (всего исправлений: 1)
void
fn(char **dst, const char *src, const size_t len)

Это делается не так, а так:

char * fn(char * src, size_t len)
    size_t dst_len = (len >= src_len ? src_len : len);

Ты изобрёл min(). Какбэ писать надо понятно.

    *dst = (char *) malloc(dst_len + 1);

Ублюдские пробелы + неосилил void * - иди перечитай мануальчик и выкинь свой С/С++ букварь.

    while (dst_len-- /*&& (**dst++ = *src++)*/);

Про мемкопи уже сказали.

Почему вам всегда хочется хреначить какое-то говно через указатель на указатель?

anonymous
()
Ответ на: комментарий от deep-purple

У меня не падает, но так не проканает, потому что в процессе итерации по строке меняется сам dst. Вот так у меня всё работает (вроде):

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

void fn(char **dst, const char *src, const size_t len)
{
    size_t src_len = strlen(src);
    size_t dst_len = (len >= src_len ? src_len : len);
    *dst = (char *) malloc(dst_len + 1); 
    char* tmp = *dst;
    while (dst_len-- && (*(*dst)++ = *src++));
    *dst = tmp;
    *(*dst + dst_len) = '\0';
}

int main(){
        char *x; 
        fn(&x, "abcde", 2); 
        printf("X: %s\n", x); 
        return 0;
}

Но тут было бы проще сразу по tmp итерироваться и т.п.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от deep-purple

Ага [sarcasm]

Конкретней, к чему тут сарказм?

как и оригинальный strndup сорс которого я скинул парой постов выше ))

как и «оригинальный strndup сорс» что?

anonymous
()
Ответ на: комментарий от anonymous

Это делается не так, а так

JFF был в том, чтобы работать с переданным аргументом, а возвращать только статус отработки.

Ты изобрёл min()

И в каком он заголовочнике задифайнен? Слышал я, что чем меньше инклюдишь, тем меньше вес прожки. В противном случае тогда можно на пыхпых-жаве итти писать, там уже всеравно, метром больше метром меньше..

Ублюдские пробелы

Ссылку на стандарт, пожалуйста, я не против исправиться.

неосилил void *

Я конечно много (наверн 99%) не понимаю, но, каким боком он тут нужен если заранее известно что везде будет char?

Про мемкопи уже сказали

Да, поставил даже memmove на всякий случай.

Почему вам всегда хочется

Ну вот он я. Научи как правильно, я впитываю.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от Ivan_qrt

Но тут было бы проще сразу по tmp итерироваться и т.п.

Да, тоже была идея добавить еще одну переменную и по ней бежать, но к тому моменту я всеравно в указателях уже запутался.

Да решено уже. Спасибо.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

К чему ты это запастил? Как это связано с моим первоначальным постом, да и предыдущими вопросами?

anonymous
()
Ответ на: комментарий от Deleted

Щас прибежит царь и обосрёт строку if(!(*dst = malloc(len+1))) return NULL;

Странно, эта портативная кукарекалка прибежала, но свой рассказ о том, что его говнокод работает только на «нормальном» конпеляторе «нормальной» ОС еще не рассказала.

Pavval ★★★★★
()
Ответ на: комментарий от anonymous

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

К чему ты это запастил?

Сабж:

Эдик: Я знаю, что нет нужды в такой проверке, но на всякий пожарный лучше делать. Мало ли, вдруг будет архитектура, на которой эта проверка будет иметь смысл?

Анон: Не волнуйся, на такой архитектуре это говно а) не запуститься, б) упадёт ещё быстрее по сотне других причин.

Диперпл: Ага [sarcasm], как и оригинальный strndup

А теперь открой ссыль и опонось тамошний стрндап сравнив его с эдиковым вариантом.

deep-purple ★★★★★
() автор топика
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Я не очень понял смысла этого кода. В функциях вида smthNsmth(dst, n, ...) n нужно для определения размера dst буфера. В функции strdup dst мы генерируем сами, поэтому в чем смысл твоего кода не ясно.

Reset ★★★★★
()
Ответ на: комментарий от Reset

Вообще-то он приложил листинг библиотечной функции. А нужно это, если хочется скопировать строку, но так, чтобы длина была не больше N.

Eddy_Em ☆☆☆☆☆
()

Всего два уровня? А вот в libjpeg суровые пацаны сделали аж 5-6.

anonymous
()
Ответ на: комментарий от deep-purple
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

char *strndup(const char *src, size_t common_length) {
  char *dest;
  size_t len = strlen(src);

  int n, r;
  n = common_length / len;
  r = common_length % len;

  dest = (char *)malloc(common_length + 1);
  dest[common_length] = '\0';
  if (!dest)
    return NULL;

  int i_n = 0;

  while (i_n < n) {
    memcpy(dest + i_n * len, src, len);
    i_n++;
  }
  memcpy(dest + i_n * len, src, r);
  return dest;
}

int main(int argc, char *argv[]) {
  char *src = "Hello";
  char *result = strndup(src, 13);
  printf("%s\n", result);
  free(result);
  return 0;
}

немного модифицировал

anonymous
()

пацаны, простите ради Бога, кто такой Царь? Я реально не в теме, думал, что так эдди называют

anonymous
()
Ответ на: комментарий от deep-purple

вот и начинай себе молча, обмазавшись книжками, нефиг сюда тащить

unt1tled ★★★★
()
Ответ на: комментарий от deep-purple

я не понимаю твоих терзаний: используй memcpy(3), а что-бы скопировать '\0', копируй на 1 чар больше длинны.

Слышал я, что чем меньше инклюдишь, тем меньше вес прожки. В противном случае тогда можно на пыхпых-жаве итти писать

плюнь в рожу тому, кто это сказал. Какая тебе разница, будет у тебя код в 40К или в 50К? Это же сишка!

emulek
()

часть закомментирована, падает на **dst++

если не уверен в приоритете, ставь скобки. Если уверен — всё равно ставь. Я ставлю. Т.е. while((*((*dst)++)=*(src++))); как-то так. Вложенность скобок надо проверять в нормальном редакторе, типа VIM'а.

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.