Про указатели и ссылки с Coursera (программа в теме) - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Начал изучать один курс на Coursera: The Hardware/Software Interface. Там все объясняется через язык программирования Си. А так как я до этого ничего не знал по нему, поэтому для меня все с нуля почти. И первое же задание меня поставило в тупик. Наверное я просто туп, это понятно. Но хочу разобраться. Может еще и мой английский не самого высокого уровня. Итак программа:
// These #includes tell the compiler to include the named
// header files, similar to imports in Java. The code for
// these is generally located under /usr/include/, such
// as /usr/include/assert.h. assert.h contains the
// declaration of the assert() function, stdio.h contains
// the declaration of the printf() function, and stdlib.h
// contains the declaration of the malloc() and free()
// functions, all of which are used in the code below.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
 
// Fill the given array with values. Note that C doesn't
// keep track of the length of arrays, so we have to
// specify it explictly here.
void fillArray(int* array, int len) {
  printf("Filling an array at address %p with %d "
         "values\n", array, len);
  for (int i = 0; i < len; ++i) {
    array[i] = i * 3 + 2;
    // assert() verifies that the given condition is true
    // and exits the program otherwise. This is just a
    // "sanity check" to make sure that the line of code
    // above is doing what we intend.
    assert(array[i] == i * 3 + 2);
  }
  printf("Done!\n");
}
 
// Structs are simply storage for memory of various types.
// In this case, we are typedef-ing (as in naming) a
// struct containing four integers as FourInts.
typedef struct {
  int a, b, c, d;
} FourInts;
 
// main() is the entry point of the program.
int main(int argc, char* argv[]) {
  // Create a new array capable of storing 10 elements
  // and fill it with values using the function declared
  // above. Arrays declared in this manner are located on
  // the stack, which is where statically allocated (as
  // in not at runtime) memory is stored.
  int array[10];
  // The "array" that we pass here is actually a pointer
  // to a block of memory capable of storing 10 integers.
  // array[0] is the first integer in this block of
  // memory, array[1] is the second, and so on. Since
  // C does not track array lengths, we have to specify
  // how many elements the array contains.
  //
  // TODO(1): What happens if the second argument is set
  // to 11 instead? How about 100? 1000? Make sure to set
  // the second argument back to 10 when you are done
  // testing.
  // Answer:
  fillArray(array, 10);
 
  int value;
  // In C, we can take the address of something using the
  // & operator. &value is of the type int*, meaning that
  // it is a pointer to an integer (as in it stores the
  // address in memory of where the actual int is located).
  //
  // TODO(2): We can actually use the address of the value
  // declared here as if it were an array of a single
  // element; why is this possible?
  // Answer:
  fillArray(&value, 1);
  // fillArray should set value to 0 * 3 + 2 = 2.
  assert(value == 2);
 
  // The following creates an instance of FourInts on the
  // stack. FourInts is really just an array of four ints,
  // although we can refer to the ints stored in it by
  // name as well.
  FourInts four_ints;
  // Set the first int to have a value of 0 and verify
  // that the value changed.
  four_ints.a = 0;
  assert(four_ints.a == 0);
 
  // Depending on whether or not you like to live
  // dangerously, the following is either exciting or
  // terrifying. Though &four_ints is of type FourInts*
  // (as in a pointer to a FourInts struct), we can
  // use a cast to pretend that it is actually an array
  // of integers instead.
  fillArray((int*) &four_ints, 4);
  // We can confirm that fillArray updated the values
  // in the FourInts struct:
  assert(four_ints.a == 2);
  assert(four_ints.b == 5);
  assert(four_ints.c == 8);
  assert(four_ints.d == 11);
 
  // In the case that the size of an array is not known
  // until runtime, the malloc() function can be used to
  // allocate memory dynamically. Memory that is
  // allocated dynamically is stored on the heap, which
  // is separate from the stack. C is unlike Java,
  // however, in that dynamically-allocated memory must
  // be freed explicitly when the program is done using
  // it via the free() function. malloc() takes a single
  // argument, which is the number of bytes to allocate.
  // sizeof(int) gives how many bytes an int contains
  // (which is four), so sizeof(int) * 5 is 20.
  int* heap_array = (int*) malloc(sizeof(int) * 5);
  fillArray(heap_array, 5);
  // Now that we have finished with the heap-allocated
  // array, free() the memory associated with it.
  //
  // TODO(3): What happens if we remove the free()
  // statement below? Try running "valgrind ./arrays"
  // after compiling the program both with and without
  // it. valgrind is a tool for analyzing how programs
  // use memory, which is often invaluable for C and
  // C++ programming.
  // Answer:
  free(heap_array);
 
  // TODO(4): Now it's your turn to write some code.
  // Using malloc(), allocate a FourInts struct
  // dynamically (on the heap) and use fillArray to
  // populate it with values. Make sure to free the
  // memory when you are done, and use the valgrind
  // tool mentioned above to check that there aren't
  // any errors. As a "sanity check," add four assert
  // statements to verify that the a, b, c, and d
  // fields of the FourInts struct are set to what
  // you would expect. (Hint, you'll need to use the
  // -> operator to access fields of a FourInts*
  // variable instead of the . operator).
  return 0;
}
Ну и для кого будет удобнее она же без комментариев:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
 
void fillArray(int* array, int len) {
  printf("Filling an array at address %p with %d "
         "values\n", array, len);
  for (int i = 0; i < len; ++i) {
    array[i] = i * 3 + 2;
    assert(array[i] == i * 3 + 2);
  }
  printf("Done!\n");
}
 
typedef struct {
  int a, b, c, d;
} FourInts;
 
int main(int argc, char* argv[]) {
  int array[10];
  fillArray(array, 10);
 
  int value;
  fillArray(&value, 1);
  assert(value == 2);
 
  FourInts four_ints;
 
  four_ints.a = 0;
  assert(four_ints.a == 0);
 
  fillArray((int*) &four_ints, 4);
 
  assert(four_ints.a == 2);
  assert(four_ints.b == 5);
  assert(four_ints.c == 8);
  assert(four_ints.d == 11);

  int* heap_array = (int*) malloc(sizeof(int) * 5);
  fillArray(heap_array, 5);
 
  free(heap_array);
 
  return 0;
}
Я настолько нуб, что самому стыдно, поэтому можете ругать сразу и пострайтесь громко не смеятся с моего понимания Итак по порядку в программе, как я её понимаю. 1.Для начала мы подключаем файлы из стандартных библиотек, которые нам понадобятся для выполнения программы. 2.После мы объявляем функцию fillArray, которая ничего не возвращает. У функции два аргумента. Первый аргумент это указатель на int с адресом массива и второй длина массива типа int. А вот дальше не очень понимаю. Выводит адрес массива, потому что имя массива возвращает указатель на первый элемент? и длину (!этот момент я не очень понял) И дальше для каждого элемента массива присваивает значение i * 3 + 2, где i номер позиции в массиве. Ну далее проверка assert и вывод Done it! 3. Потом создаем структуру из данных a,b,c,d типа int и присваиваем ему свой тип FourInts. 4. После начинается сама программа. main для начала как и везде. И объявляем массив с размером 10 (этот массив занимает 4 * 10 = 40 байт (сумма 4-битных слов)) 5. Передаем этот массив в функцию со значениями array и длиной 10. Тут же первый вопрос: TODO(1): What happens if the second argument is set to 11 instead? How about 100? 1000? Make sure to set the second argument back to 10 when you are done testing. Я проверил, если ввести любое число, то адрес не поменяется, только меняется само значение value при исполнении, что и понятно. А вот адрес не меняется так как указатель на массив не меняется вне зависимости от длины, так как имя массива возвращает указатель на первый элемент? 6. Объявляем переменную value типа int. Дальше TODO(2): We can actually use the address of the value declared here as if it were an array of a single element; why is this possible? Этот вопрос я совсем не понял. 7. Передаем в функцию fillArray аргументы &value - адрес value и длину 1. Проверяем, что значение действительно равно 2. 8. Объявляем переменную four_ints типом FourInts. 9. Приваиваем four_ints.a значение 0 и проверяем. 10. Передаем в функцию fillArray ссылку на указатель fiur_ints и длину 4. 11. Проверяем все значения. 12. Адрес некоторого нулевого значения массива heap_array присваиваем значение выделеной памяти под 5 элементов. Тем самым показывая как динамически выделять память под указатель массива. 13. Опять передаем в функцию fillArray массив heap_array и длину 5. 14. Освобождаем выделенную память. TODO(3): What happens if we remove the free() statement below? Try running "valgrind ./arrays" after compiling the program both with and without it. valgrind is a tool for analyzing how programs use memory, which is often invaluable for C and C++ programming. Когда закончил работать с памятью, которую ранее выделили, необходимо освободить её, иначе это может вызвать утечку памяти или ошибки. 15. Заканчиваем программу. А самый главный вопрос, я не понимаю, что я должен сделать сам вот по этому пункту: TODO(4): Now it's your turn to write some code. Using malloc(), allocate a FourInts struct dynamically (on the heap) and use fillArray to populate it with values. Make sure to free the memory when you are done, and use the valgrind tool mentioned above to check that there aren't any errors. As a "sanity check," add four assert statements to verify that the a, b, c, and d fields of the FourInts struct are set to what you would expect. (Hint, you'll need to use the -> operator to access fields of a FourInts* variable instead of the . operator). Помогите встать на путь программирования.

Решение задачи: «Про указатели и ссылки с Coursera (программа в теме)»

textual
Листинг программы
size_t siz = sizeof(array) / sizeof(array[0]);

Объяснение кода листинга программы

  1. В данном коде объявлена переменная siz типа size_t, которая используется для хранения результата вычисления выражения sizeof(array) / sizeof(array[0]).
  2. array - это имя массива, на который указывает переменная array.
  3. array[0] - это первый элемент массива array.
  4. sizeof(array) - это размер массива array в байтах.
  5. sizeof(array[0]) - это размер одного элемента массива array в байтах.
  6. Результат вычисления sizeof(array) / sizeof(array[0]) будет равен количеству элементов в массиве array.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

7   голосов , оценка 4 из 5
Похожие ответы