0

guys im extremely new to C++ and want to ask a few questions about allocating memory in c++. Sorry if this seems like a basic questions, but below i have an allocated memory address using malloc. Malloc uses a multiple of the size of an integer, this returns a void pointer but in then cast into an integer pointer. Why is the assignment to integer allowed if it technically doesnt actually pointer to an integer size region of memory, but a multiple of integer sized memory?

#include <stdio.h>
#include <stdlib.h>
int main() {
   int n = 4, i, *p, s = 0;
   p = (int*) malloc(n * sizeof(int));
   if(p == NULL) {
      printf("\nError! memory not allocated.");
      exit(0);
   }
   printf("\nEnter elements of array : ");
   for(i = 0; i < n; ++i) {
      scanf("%d", p + i);
      s += *(p + i);
   }
   printf("\nSum : %d", s);
   return 0;
}
Yogi Bear
  • 3
  • 4
  • 3
    In C++ there's never a reason to use `malloc` or `free`, only `new` or `delete`. Are you sure that you're trying to learn C++ instead of C, a completely different language? What's the textbook you're using, is it for C or C++? And if you're actually trying to learn C++, there's never much of a reason to use `new`. Modern C++ code almost never does this, and simply uses one of many containers from the C++ library that manages all memory allocation for you correctly. – Sam Varshavchik Jul 11 '21 at 14:18
  • (1) never use `malloc/free`, (2) almost never use `new/delete`; for the code above use `std::vector my_vector(n);` see https://en.cppreference.com/w/cpp/container/vector The code in your question is pure `C` (a different lanugage). – Richard Critten Jul 11 '21 at 14:18
  • It seems you are coming to C++ from a C background. In my opinion it is harder to learn C++ with C preconceptions. Just about every good C habit and programming strategy is considered a bad habit or anti-pattern in C++. Almost all of the above code should just be `std::vector p(4);`. – François Andrieux Jul 11 '21 at 14:23
  • Im not reading any text books, but i was reading about memory alignment and an example came up using C++ as a demonstration. I studied C++ around 5 years ago so just cam back to revisit parts of C++ to understand the example – Yogi Bear Jul 11 '21 at 14:23
  • 1
    @YogiBear You are best re-tagging your question `C` as in C++ this is not recommended code/coding style. And you will most likely get all the C++ people saying _"don't do it like that"_ – Richard Critten Jul 11 '21 at 14:24
  • what are the particular reasons for using containers over new and malloc? Im guessing for malloc memory leaks what about new? – Yogi Bear Jul 11 '21 at 14:26
  • @YogiBear `new` should be hidden behind smart pointers; but even those can usually be replaced with `std::vector` (or other container). STD containers abstract the memory management from you with no overhead (you would have to write the code anyway). – Richard Critten Jul 11 '21 at 14:29
  • Interesting, i will take a look a tthem again thanks – Yogi Bear Jul 11 '21 at 14:30
  • BTW, it’s best not to [cast the result of malloc()](https://stackoverflow.com/a/605858/643383). – Caleb Jul 11 '21 at 14:35

2 Answers2

1

I assume you're referring to this line p = (int*) malloc(n * sizeof(int));.

You're not assigning to an integer, but to an integer pointer, p is declared as int* p. malloc returns an address to a block of memory, in this case of int. void pointer can be cast to anything, but we know it's a pointer to a block int which is why there is the appropriate casting.

ShadowMitia
  • 2,411
  • 1
  • 19
  • 24
0

You are allocating enough dynamic memory to hold an array of n number of ints, and then you are pointing p at the 1st int in that memory. So why wouldn't you expect the assignment to succeed? An int* pointer can point at an int.

But, you really shouldn't be using malloc() (and scanf() and printf()) in C++ at all. C++ is not C, they are different languages, with different ways of doing things. Use new (and std::cin and std::cout) in C++ instead:

#include <iostream>

int main() {
    int n = 4, *p, s = 0;
    p = new int[n];
    std::cout << "\nEnter elements of array : ";
    for(int i = 0; i < n; ++i) {
        std::cin >> p[i];
        s += p[i];
    }
    delete[] p;
    std::cout << "\nSum : " << s;
    return 0;
}

Or, in C++11 and later, you can use std::unique_ptr to handle the delete[] for you (and the new[] in C++14 and later):

#include <iostream>
#include <memory>

int main() {
    int n = 4, s = 0;
    auto p = std::make_unique<int[]>(n); // C++14 and later
    // std::unique_ptr<int[]> p(new int[n]); // C++11
    std::cout << "\nEnter elements of array : ";
    for(int i = 0; i < n; ++i) {
        std::cin >> p[i];
        s += p[i];
    }
    std::cout << "\nSum : " << s;
    return 0;
}

However, whenever you need a dynamic array, you should prefer to use the standard std::vector container instead. Let it handle the allocation and cleanup of the dynamic memory for you:

#include <iostream>
#include <vector>

int main() {
    int n = 4, s = 0;
    std::vector<int> p(n);
    std::cout << "\nEnter elements of array : ";
    for(int i = 0; i < n; ++i) {
        std::cin >> p[i];
        s += p[i];
    }
    std::cout << "\nSum : " << s;
    return 0;
}

Though, in this particular case, you are not actually using the array for anything meaningful, so you can just get rid of the array completely, a single int will suffice:

#include <iostream>

int main() {
    int n = 4, v, s = 0;
    std::cout << "\nEnter elements of array : ";
    for(int i = 0; i < n; ++i) {
        std::cin >> v;
        s += v;
    }
    std::cout << "\nSum : " << s;
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770