LINUX.ORG.RU

Тупняк и указатели

 


1

1
int n=10;
arr=malloc(sizeof(int)*n); 
for(int i=0;i<n;i++){
*(arr+i)=i;
}

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

while
? Или перефразируем: как будет выглядеть этот код у профессионала?

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 1)

профессионал скастует результат маллока к int*, чтобы не варнинговал компилятор, проверит, что вернулся не нулл, и напишет a=i, потому ято красивее и понятнее

anonymous
()

Я бы так написал (C99, раз int внутри for).

#include <stddef.h>
#include <stdlib.h>
// ...
const int N = 10;
int *const arr = malloc(sizeof(*arr)*N);
if (arr == NULL) {
    // ...
}
for (int i = 0; i < N; ++i) {
    arr[i] = i;
}
while тут плох, так как речь идёт о диапазоне, а это как раз for.

UPD: ещё можно size_t использовать для N и i, но тогда надо повышать бдительность к операциям с беззнаковыми типами.

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

конечно же, я имел в виду оператор квадратных скобок, но его съел парсер

anonymous
()

поскольку malloc возвращает void *, эстетичнее будет привести void* к int*. тред не читал

IvanR ★★★
()

что-то туплю от жары =). Выражение

*(arr+i)
можно заменить на инкремент указателя?

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

профессионал скастует результат маллока к int*

Если это профессионал C++, то он будет использовать new. Если это профессионал C, то кастовать он не будет, так как void* указатели кастовать излишне.

i-rinat ★★★★★
()

как будет выглядеть этот код у профессионала?

arr[i] = i;
x0r ★★★★★
()
Последнее исправление: x0r (всего исправлений: 1)
Ответ на: комментарий от int13h

Смотри, ещё для тебя есть:

#include<stdio.h>

int main(){
  char a[]="zxcv";
  putchar(1[a]);}

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

Или вот, настоящие про пишут так:

#include<stdio.h>

int main(){
  putchar(*(2+"zxcv"));}
Птушников выше не слушай.

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

Я обычно так делаю

Зачем? Во-первых, это убивает читаемость. Во-вторых, компилятор не такой уж тупой.

mix_mix ★★★★★
()

Профессионал знает что [] это макрос, и в рантайме между обращением к элементу массива через указатель или через [] разницы нет никакой. А раз разницы нет, то минимализм и читабельность в приоритете. Вывод — профессионал напишет с [].

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

Потому что вы потеряете указатель для последующего free. инкрементировать указатели можно/лучше при конструкции

int i, *arr,*ptr;
arr=malloc(size);
ptr=arr;
for(i=0;i<10;i++){
*ptr++=i
}
.....

free(arr);

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

Не, все работает. Да, и как лучше

*ptr++
или
*(ptr+i)
? В первом случае, чтобы в дальнешем работать с этим указателем, его надо «обнулить»? Вернуть на первый элемент в области выделенной маллоком памяти, так?

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

free(arr);

обнулять

да, верно. понял.

int13h ★★★★★
() автор топика
Ответ на: комментарий от anonymous
int *a = (int [10]){0,1,2,3,4,5,6,7,8,9};

Это точно по-царски. Я забыл про выделение памяти прямо в мозгу, а то malloc тормозит.

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

Ты всех лоркодом пришел потроллить? Парни, [i] пишется с удвоением квадратных скобок.

По теме: профессионал не станет маллочить и заполнять массив интов, чтобы определить идентичное отображение от 0 до 9.

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

По теме: профессионал не станет маллочить и заполнять массив интов, чтобы определить идентичное отображение от 0 до 9.

здесь этот код для примера

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

профессионал не станет маллочить и заполнять массив интов, чтобы определить идентичное отображение от 0 до 9.

Воткнет туда выхлоп seq -s&#34;, &#34; 0 9?

А можно и так:

int a[] = { A_INIT };

Заполнять так:

gcc ... -DA_INIT="$(seq -s", " 0 9)"

Вот пример:

cat 1.c 
#include <stdio.h>
int main(int c, char **v){
	int i, a[] = { A_INIT }, L = sizeof(a)/sizeof(int);
	for(i=0; i < L; i++) printf("a[%d] = %d\n",i,a[i]);
	return 0;
}
gcc 1.c -Wall -Werror  -DA_INIT="$(seq -s", " 0 9)" && ./a.out 
a[0] = 0
a[1] = 1
a[2] = 2
a[3] = 3
a[4] = 4
a[5] = 5
a[6] = 6
a[7] = 7
a[8] = 8
a[9] = 9
gcc 1.c -Wall -Werror  -DA_INIT="$(seq -s", " -5 5)" && ./a.out 
a[0] = -5
a[1] = -4
a[2] = -3
a[3] = -2
a[4] = -1
a[5] = 0
a[6] = 1
a[7] = 2
a[8] = 3
a[9] = 4
a[10] = 5
Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от int13h

Лучше calloc использовать. Дольше, зато "неожиданностей" не будет, если что (особенно полезно так под структуры память выделять — все указатели внутри них будут NULL, а не ХЗчо).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от int13h

Ну, как бэ, если тебе и дальше надо с указателем этим работать начиная с первого элемента - то нормально. А вообще - для получения понятия стиля можно почитать исходники ядра. В целом, там всё красиво и читаемо, если не учитывать некоторые неявные define'ы и inline'ы, в которых происходит кастинг переменных, что добавляет головной боли при работе с тем же новомодным netlink.

Возвращаясь к читаемости, красивее код в цикле выглядит с квадратными скобочками:

for(i=0;i<n;i++){
arr[i]=i;
}
, но это уже моё субъективное.

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

Теперь я догадываюсь, почему в gcc такой дохлый препроцессор: ведь можно все нагенерировать баш-скриптами на стадии cmake.

А я простыни-портянки писал для автоматического определения функций для CUDA и OpenMP одновременно (в зависимости от возможностей вызывается либо кудовая, либо опенмпнутая)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от nickleiten

Я просто труд по C какого-то автора читал, где он паскалистами и любителями бейсика обзывал стиль a[i] =)

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

Эк куда тебя унесло. Я имел ввиду, что достаточно в уме знать границы 0..n, кода для этого вообще не требуется, кроме первой строчки.

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

К каждой книге/учебнику нужно относиться как книге/учебнику, а не библии :) Сколько срачей вокруг goto, а иногда всё-равно приходится пользоваться - сколько драйверов с ним внутри сидит...

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

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

паскалистами

Смерд называет благородных донов благородными.

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

Тех, кто плюется от goto, можно смело посылать на какое-нибудь количество букв. Потому что очень много чего без goto превратится в Содом и Гоморру! И внутри макросов удобно (скажем, какое-то условие не отработало — делаем сразу переход к концу функции, где освобождается память).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от int13h

Если хочешь добраться до вымени - попробуй, очистив от лишнего увидеть этот код на asm.

Наверное, здесь подскажут, как оптимально добраться до просмотра в asm т.к. может лишнее подцепиться...

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

Полный текст будет выглядеть так

int i,n=9,*arr,*arr_;
arr_=calloc(sizeof(int)*n);
for(arr=arr_, i=0; i<n; arr[i]=i++);
arr=arr_;

Экономия места на экране с помощью оператора «запятая», которая позволяет делать последовательно несколько примитивных действий в одном блоке. В данном случае мы берём адрес указателя и присваиваем его в arr (в цикле for, в скобочках до первой точки-запятой команды исполняются при входе в цикл) и присваиваем i=0, потом начинается сам цикл, проверяется условие и действие, а т.к. действие можно совместить с пост-инкрементом, в конце всё и просиходит, при этом само тело цикла нам не требуется. Это тонкости работы с компиляторами, и область понимания, что происходит при прохождении парсинга c-кода в asm-код.

Для примера немного жуткого кода, заменяющего табы на пробелы и заменяющего несколько подряд идущих пробелов одним и в конце функции убирает пробелы в начале и в конце строки:

void cut_spacetabs(char *str){
	char *c,*t;
	/* Replace tabs with spaces */
	for(c=str,t = strchr(c,'\t'); (t - str <= strlen(str)) || (t != NULL); t = strchr(c,'\t')) t[0]=' ';
	c=NULL;t=NULL;
	/* Leave one space on place of several */
	for(c = str, t = strchr(c,' '); (t - str <= strlen(str)) || (t != NULL); t = strchr(c,' '))
		if ( t[1] == ' ' ){
			memmove(t, t + 1, strlen(str) - (str - t) + 1);
			c=t;
		}else
			c++;
	if(str[0] == ' ')
		memmove(str, str + 1, strlen(str));
	if(str[strlen(str)-1] == ' ')
		str[strlen(str)-1]='\0';
}

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