LINUX.ORG.RU

Несколько вопросов новичка по Си

 , ,


0

3
  1. Как работает указатель?
  2. Функция sub получает делимое и вычитает из него делитель Она ничего не возвращает и просто меняет значение переменой по указателю. Но когда вызываю функцию, приходится указывать & и имя переменной. Нельзя ли просто передать переменную и почему?
    void sub(int* f, int g)
    {
      *f = *f - g;
    }
    
    int main(void)
    {
      int number = 15, div = 7;
      sub(&number, div);
      printf("%d\n", number);
      return 0;
    }
  3. Насколько этот код говно? Что стоило бы исправить? Спасибо!
★★

Указатель указывает на место в памяти, куда уж проще.

Суть обращения функции к указателю переменной в использовании самой переменной, а не копии.

Bfgeshka ★★★★★
()

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

Iron_Bug ★★★★★
()

mystery

Как работает указатель?


Reedych

Неплохо

mos ★★☆☆☆
()

Что стоило бы исправить?

Не использовать указатель, а возвращать значение.

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

Неплохо что? Ты имел в виду сказать «не плохо»? Так чем ты сегодня закинулся, ты так и не ответил?

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

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

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

Если я задаю int* ptr = &var, получается, что ptr - переменная, хранящая адрес в памяти, где содержится переменная var?

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

K&R почитываю, но особо не углубляюсь, просто очень интересная эта тема, но съедает много времени
Хотелось бы объяснения на двух пальцах

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

Собирается, но это уже получается Си++, а мне Си++ не нравится
Ладно, буду передавать с амперсандом, просто ради интереса спросил

mystery ★★
() автор топика

Но когда вызываю функцию, приходится указывать & и имя переменной.

Ну да, так ты адрес переменной получаешь

void sub(int* f, int g)

Если бы здесь ты припилил возвращаемое значение, изменил аргумент с указателя просто на int, то обошелся бы без &

int sub(int f, int g) {
	return f - g;
}

int main(void) {
  int number = 15, div = 7;

 
  printf("%d\n", sub(number, div));

  return 0;
}

Нельзя ли просто передать переменную и почему?

Потому что типы разные, функция принимает указатель на int, а передавал бы ты int.

void sub(int *f, int g) {
	*f -= g;
}

int main(void) {
  int number = 15, div = 7;
  int *n = &number;

  sub (n, div);
  printf("%d\n", number);

  return 0;
}

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

он издевался, указывая на плюсовые ссылки. в С этого нет.

не страдай фигнёй, читай теорию. методом перебора это не работает.

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

Спасибо
Вариант с return очивиден, но мне интересна работа с указателями

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

не ищи объяснения на двух пальцах. это очень просто. но надо понять один раз, чтобы потом не заниматься гаданием на кофейной гуще. это основы. и основы надо знать очень хорошо, чтобы куда-то продвигаться дальше. лучше методично изучай примеры в K&R до просветления. потому что простые указатели - это начало. есть ещё указатели на указатели, указатели на функции и прочее. один раз усвоив принцип, поймёшь всё остальное и не будешь заниматься индусским говнокодом методом имитации.

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

А в этом плане С++ крут
Буду знать, спасибо

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

А зачем нужны указатели на указатели? Просто мне сложно себе это представить
Есть ли примеры какие-нибудь?

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

Динамический двумерный массив, скажем, сделать А что представлять?

//Есть у тебя целое знаковое n
int n = 0;
//Получим адрес n
int *pn = &n;
//А теперь получим адрес указателя на n
int **ppn = &pn; //вот и получается, что ppn это указатель на pn, а pn это указатель
jasper
()
Ответ на: комментарий от mystery

А зачем нужны указатели на указатели? Просто мне сложно себе это представить

Аналогично - чтоб изменить указатель внутри функции, например.

anonymous
()
Ответ на: комментарий от mystery
void sub(int **f, int g) {
  **f -= g;
}

int main(void) {
  int number = 15, div = 7;
  int *pn = &number;
  int **ppn = &pn;
  sub (ppn, div);
  printf("%d\n", number);

  return 0;
}
jasper
()
Ответ на: комментарий от mystery

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

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

таких примеров довольно много. это не такая уж экзотика.

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

Динамический двумерный массив

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

Вообще довольно странно, что ТС читает какие-то книги и не понимает одну из базовых сущностей языка.

Bfgeshka ★★★★★
()

У меня четвертый вопрос. Почему нынче так много вопросов по сишке? Притом, базового уровня.

Указатели легко понимать, как с ними начинаешь работать. Это тупо цифра, местоположение значения твоей переменной в памяти.

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

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

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

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

Его можно и так, например, записать:

Но зачем? [static N] у параметра функции проверяет на этапе компиляции, что туда передадут массив размером не меньше N, а по сути это тот же указатель, нэ?

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

Но зачем?

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

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

У меня четвертый вопрос. Почему нынче так много вопросов по сишке? Притом, базового уровня.

ну, очевидно, кто-то его изучает. что в этом плохого? не всем на пистонах говнокодить. надо и новое поколение системщиков растить :) впрочем, С неплохо вправляет мозги в плане программирования (по крайней мере, процедурного) и полезен просто в качестве развивающего соображалку упражнения. вреда от его изучения точно не будет, даже если потом программист его и не будет использовать.

Iron_Bug ★★★★★
()

Нельзя ли просто передать переменную и почему?

Потому что в Си в функции всегда передается значение аргумента, т.е. временная копия, поэтому любые изменения этой копии никак не отразятся на оригинале. В случае передачи функции указателя на переменную (т.е. копии ее адреса), можно менять значение переменной обращаясь к ней по ее родному адресу в памяти.

anonymous
()

1. Указатель - переменная которая хранит адрес в памяти, &var это адрес какой-нибудь переменной, *ptr это значение по адресу который в указателе ptr

2. Потому-что когда-ты просто пишешь имя переменной компилятор передает ее значение, т.е. sub(number, div) это sub(15, 7), но так как тебе надо изменять number внутри функции ты передаешь адрес переменной в памяти что-бы переписать значение по этому адресу в коде функции.

3. С кодом все вроде норм

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

Я согласен, это надо. Просто я имею ввиду, что какой-то всплеск вопросов. Какой-то неожиданный. И даже не поймешь, троллинг это или правда проблемы.

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

Это я знаю, имел в виду без лишних операторов, но уже понял, что это никак

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

И вам тоже спасибо, стало намного яснее

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

сейчас рынок IoT и embedded на подъёме. кстати, и вакансий больше стало на этом поприще, и платят хорошо, потому что в основном аутсорц на заграничные компании. но технологии довольно быстро меняются, нельзя прогнозировать на много лет вперёд. в любом случае, системное программирование никуда не денется. а там и микроконтроллеры рядом стоят, там приложений просто немеряно.

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

всякие обзоры популярности ЯП показывают, что за последний год популярность С поднялась. может, и интерес к нему вырос. хотя, например, ВУЗы (и даже мой родной матмех, в бывшем УрГУ) прекратили преподавание С и плюсов, что печально. у нас была целая кафедра системного программирования и там С был в полный рост, с практикой на мультипроцессорных машинах и т.д. а что там преподают без С сейчас - я ваще хз. студенты мне рассказывали, что там «программирование микроконтроллеров на С#». я посмеялась. не, есть там какой-то фреймворк, который может ворочаться не то на АРМах, не то ещё на каких-то крупных железках (микроконтроллерами это назвать нельзя). но решение ВУЗа сменить преподавание продавлено конкретной компанией (не стану им давать рекламу, они нехорошие редиски), которая проплачивает подготовку C#-программистов для своих кадровых резервов и приплачивает факультету. в общем, бабло задавило здравый смысл. возможно, ещё на этом фоне поднялся естественный интерес студентов к тому, что не преподают (как оно обычно бывает).

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

Если точнее, то в стек всегда попадает значение. В C нет иного метода передачи параметров, кроме как по значению.

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

ну да, в итоге это число. но интерпретируется оно как адрес.

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

у нас была целая кафедра системного программирования и там С был в полный рост, с практикой на мультипроцессорных машинах и т.д.

Я бы на такое пошел. О_О

Жаль, что разрушили.

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

Теперь это днявки-тред

А я 50/50. Где теория, где перебором.

anonymous
()

Насколько этот код говно?

Лучше просто возвращать результат, чем использовать указатель.

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