C -- Trouble with pointers - c

I am new to C, know some Java.
Trying to write a program that accepts 2D array that represents a directed adjacency matrix, and two numbers, scans the array and returns true if there is a directed path between them (top-down).
I am running into a problem with C implementation. Apparently I have to use pointers to values in array, whilst in Java I could've use values from array (compare, return to function, etc).
I'm pretty sure the logic is in place, I just need help with allocating '*'s in the right places and amounts.
Here's the code:
#include <stdio.h>
#define N 12
typedef int bool;
enum {false, true};
typedef struct adj_mat{
int A [N][N];
}adj_mat;
int path(struct adj_mat A, int origin, int dest){
int i;
if (origin == dest) return true;
for (i = 0; i < sizeof(A);i++){
if (A[origin][i]){
return path (A, i, dest);
}
}
return false;
}
Thanks in advance.

for (i = 0; i < sizeof(A);i++){
This should be for (i = 0; i < N; i++){.
Also, your algorithm may not terminate since it didn't take care of cycles in graph.

sizeof(A)
This probably does not give you what you expect. It is the number of bytes, not the number of elements.
A[origin][i]
Here you are trying to index the struct adjmat which doesn't work. You probably wanted to index the member A. Try:
A.A[origin][i]
It would probably be a good idea to rename adj_mat A to something else to avoid confusion.
You should also pass the address of A to the function and use adj_mat* as the argument type. If I understand correctly you want the recursion to operate on the same object.

Related

How to make permutations in an array?

I'm new to C, and I was trying to write a function that would make permutations in array, given an array that has the new position of each elements.
An example of what I'd like to have :
int newPositions[] = {3,1,5,2,4};
int arr[] = {20,30,-1,9,1};
>> {-1,20,1,30,9}
I come from Java, so I had the basic functions we'd think of trying to do that, but I was surprised when I saw that I couldn't return an array in C, and I'm trying to find the best possible way of doing that without using too much memory. I thought about copying the array, but is there another solution?
Thanks
Here's how that could look:
#include <string.h>
void permutate(int** array, int* newPositions, int count)
{
int* arrayCopy = malloc(sizeof(int) * count);
memcpy(arrayCopy, array, sizeof(int) * count);
for (int i = 0; i < count; i++)
{
array[i] = arrayCopy[newPositions[i] - 1];
}
free(arrayCopy);
}
Be aware that arrays in C don't know their length (that's why count must be passed), so if there's a mismatch between both arrays and/or size, your program will do something unexpected or crash.
The are a lot of details to know about arrays and pointers in C. Please have a good look at this chapter of the famous C-FAQ.

looping over an array in C

Say I want to loop over an array, so I used a basic for loop and accessed each element in it with the index but what happens if I don't know how long my array is?
#include <stdio.h>
#include <stdlib.h>
int main(){
int some_array[] = {2,3,5,7,2,17,2,5};
int i;
for (i=0;i<8;i++){
printf("%d\n",some_array[i]);
}
return 0;
}
This is just a simple example but if I don't know how big the array is, then how can I place a correct stopping argument in the loop?
In Python this is not needed since the StopIteration exception kicks in, but how can I implement it in C?
Just do like this:
for (i=0; i<sizeof(some_array)/sizeof(some_array[0]); i++){
printf("%d\n",some_array[i]);
}
But do beware. It will not work if you pass the array to a function. If you want to use it in a function, then write the function so that you also pass the size as argument. Like this:
void foo(int *arr, size_t size);
And call it like this:
foo(some_array, sizeof(some_array)/sizeof(some_array[0]));
But if you have a function that just take a pointer, there is absolutely no standard way to find out the size of it. You have to implement that yourself.
You have to know the size of the array. That's one of the most important rules of C programming. You, the programmer, are always responsible for knowing how large your array is. Sure, if you have a stack array or a static array, you can do this:
int array[size];
int size_of_array = sizeof array / sizeof *array;
for (int i = 0; i < size_of_array; i++) {
// do something with each array[i]
}
But as you can see, you needed the variable size in the first place. So what's the point of trying to discover the size if you were forced to know it already?
And if you try to pass this array to any function
some_function(array); /
you have to pass the size of the array too, because once the array is no longer in the same function that declared it, there is no mechanism to find its size again (unless the contents of the array indicate the size somehow, such as storing the number of elements in array[0] or using a sentinel to let you count the number of elements).
void some_function(int *array) {
/* Iterate over the elements until a sentinel is found.
* In this example, the sentinel is a negative number.
* Sentinels vary from application to application and
* implicitly tell you the size of the array.
*/
for (int i = 0; array[i] >= 0; i++) {
// do something with array[i]
}
}
And if it is a dynamically-allocated array, then you need to explicitly declare the number of elements anyway:
int size = 10;
int *array = malloc(sizeof *array * 10);
So, to summarize, you must always know the size of the array. There is no such thing in C as iterating over an array whose size you don't know.
You can use sizeof() to get the size of the array in bytes then divide the result by the size of the data type:
size_t n = sizeof(some_array)/sizeof(some_array[0]);
In general, you can calculate the size of the array with:
sizeof(ArrayName)/sizeof(ArrayType)
but this does not work with dynamically created arrays

To know the size of an array in c

I am learning C language. I want to know the size of an array inside a function. This function receive a pointer pointing to the first element to the array. I don't want to send the size value like a function parameter.
My code is:
#include <stdio.h>
void ShowArray(short* a);
int main (int argc, char* argv[])
{
short vec[] = { 0, 1, 2, 3, 4 };
short* p = &vec[0];
ShowArray(p);
return 0;
}
void ShowArray(short* a)
{
short i = 0;
while( *(a + i) != NULL )
{
printf("%hd ", *(a + i) );
++i;
}
printf("\n");
}
My code doesn't show any number. How can I fix it?
Thanks.
Arrays in C are simply ways to allocate contiguous memory locations and are not "objects" as you might find in other languages. Therefore, when you allocate an array (e.g. int numbers[5];) you're specifying how much physical memory you want to reserve for your array.
However, that doesn't tell you how many valid entries you have in the (conceptual) list for which the physical array is being used at any specific point in time.
Therefore, you're required to keep the actual length of the "list" as a separate variable (e.g. size_t numbers_cnt = 0;).
I don't want to send the size value like a function parameter.
Since you don't want to do this, one alternative is to use a struct and build an array type yourself. For example:
struct int_array_t {
int *data;
size_t length;
};
This way, you could use it in a way similar to:
struct int_array_t array;
array.data = // malloc for array data here...
array.length = 0;
// ...
some_function_call(array); // send the "object", not multiple arguments
Now you don't have to write: some_other_function(data, length);, which is what you originally wanted to avoid.
To work with it, you could simply do something like this:
void display_array(struct int_array_t array)
{
size_t i;
printf("[");
for(i = 0; i < array.length; ++i)
printf("%d, ", array.data[i]);
printf("]\n");
}
I think this is a better and more reliable alternative than another suggestion of trying to fill the array with sentinel values (e.g. -1), which would be more difficult to work with in non-trivial programs (e.g. understand, maintain, debug, etc) and, AFAIK, is not considered good practice either.
For example, your current array is an array of shorts, which would mean that the proposed sentinel value of -1 can no longer be considered a valid entry within this array. You'd also need to zero out everything in the memory block, just in case some of those sentinels were already present in the allocated memory.
Lastly, as you use it, it still wouldn't tell you what the actual length of your array is. If you don't track this in a separate variable, then you'll have to calculate the length at runtime by looping over all the data in your array until you come across a sentinel value (e.g. -1), which is going to impact performance.
In other words, to find the length, you'd have to do something like:
size_t len = 0;
while(arr[len++] != -1); // this is O(N)
printf("Length is %u\n", len);
The strlen function already suffers from this performance problem, having a time-complexity of O(N), because it has to process the entire string until it finds the NULL char to return the length.
Relying on sentinel values is also unsafe and has produced countless bugs and security vulnerabilities in C and C++ programs, to the point where even Microsoft recommends banning their use as a way to help prevent more security holes.
I think there's no need to create this kind of problem. Compare the above, with simply writing:
// this is O(1), does not rely on sentinels, and makes a program safer
printf("Length is %u\n", array.length);
As you add/remove elements into array.data you can simply write array.length++ or array.length-- to keep track of the actual amount of valid entries. All of these are constant-time operations.
You should also keep the maximum size of the array (what you used in malloc) around so that you can make sure that array.length never goes beyond said limit. Otherwise you'd get a segfault.
One way, is to use a terminator that is unique from any value in the array. For example, you want to pass an array of ints. You know that you never use the value -1. So you can use that as your terminator:
#define TERM (-1)
void print(int *arr)
{
for (; *arr != TERM; ++arr)
printf("%d\n", *arr);
}
But this approach is usually not used, because the sentinel could be a valid number. So normally, you will have to pass the length.
You can't use sizeof inside of the function, because as soon as you pass the array, it decays into a pointer to the first element. Thus, sizeof arr will be the size of a pointer on your machine.
#include <stdio.h>
void ShowArray(short* a);
int main (int argc, char* argv[])
{
short vec[] = { 0, 1, 2, 3, 4 };
short* p = &vec[0];
ShowArray(p);
return 0;
}
void ShowArray(short* a)
{
short i = 0;
short j;
j = sizeof(*a) / sizeof(short);
while( i < j )
{
printf("%hd ", *(a + i) );
++i;
}
printf("\n");
}
Not sure if this will work tho give it a try (I don't have a pc at the moment)

Why does this C code work?

EDIT: Thank you very much for your responses. I understand this properly now!
I am trying to learn more on C pointers. Tinkering around, I am questioning the difference between two actions I am using.
This code seems to work at first glance, but I am not sure of what's the difference, and if any of these two approaches is wrong in some way.
I'd like to know what's the difference between the two pieces of code, when I should I pass the adress, and when a pointer to an array?
Is any of the pieces wrong? If so, what would be the proper way?
having a simple struct grid pretty much like struct grid { int val; } (for demonstration purposes)
First piece of code. Passing address of the pointer to the array.
void set (mygrid *grid, int foo){
grid->bar = foo; //should this be '*grid->bar?' But this seems to work properly.
}
void main(){
int i;
int* array;
int max = 24;
array = malloc(sizeof(grid) * max);
for(i = 0; i < max; i++){
set(&array[i], 0);
}
}
Second piece of code. I am not entirely sure why this works, but the compiler doesn't output any warning.
I am supposed to be passing the pointer to the start of the array like this?
void set(mygrid *grid, int foo){
int i; int max = 24; //so this example code compiles :P
for(i = 0; i < max; i++){
grid[i].bar = foo;
}
}
void main(){
int* array;
int max = 24;
array = malloc(sizeof(grid) * max);
set(array, 0); //Why not &array?
}
Passing an array decays into a pointer that points to the first member of the array, just like &array[0].
In your second example, array is just a pointer, and the return value from malloc is just the address of the start of the block of memory you get.
It doesn't have to be used for an array; it could be used for storage of an arbitrary sizeof(int) * max bytes of data. An array (in C) is really just a nice way of thinking about & working with a solid block of memory divided up into equal size portions.
Secondly, you should understand how my_array[i] works. All it does is take the address of where your block of array data starts (which is the actual value of my_array), and then look at what value is stored at a particular offset from there. Specifically, if my_array is of a (made up) type of WhatEver, then it will access the data from my_array + i*sizeof(WhatEver) to my_array + (i+1)*sizeof(WhatEver).
On a related note (since you're learning C), it's highly recommended to check that the return from malloc is not NULL before doing anything with it.
I'm no C guru but am also trying to improve my understanding so if this is incorrect, please leave a comment or edit my answer so I can learn from my mistakes :)
In your first piece of code
grid->bar is same as (*grid).bar
. and using name of an array refers to its base address. so writing array is equivalent &array[0]
&array[i] is equivalent to array+i
array[i] is equivalent to *(array +i)
In you second piece of code i dont understand why there is no error because in your function set you do not declare max and i dont see a global max variable too.
also in your second piece of code you use
set(array,0) because array is already an integer pointer(see the declaration int * array).As far as i understand the mygrid is not a struct but is an array of structs in the second example
In C, an array is pretty much the same as a pointer. For me this isn't so amazing, since it is one of the earlier programming languages I learned, but if you're coming from a high level language where an array is a different type of object, then it might come across as strange.

Dynamic Memory storage issue after realloc - C

For an assignment at school, we have to use structs to make matrices that can store a infinite amount of points for an infinite amount of matrices. (theoretical infinite)
For the assignment I decided to use calloc and realloc. How the sizes for the matrix go is: It doubles in size every time its limit is hit for its points (so it starts at 1, then goes to 2, then 4 and so on). It also doubles in size every time a matrix is added as well.
This is where my issue lies. After the initial matrix is added, and it goes to add the second matrix name and points, it gives me the following:
B???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
B is the portion of it that I want (as I use strcmp later on), but the ? marks are not supposed to be there. (obviously)
I am not sure why it is exactly doing this. Since the code is modular it isn't very easy to get portions of it to show exactly how it is going about this.
Note: I can access the points of the matrix via its method of: MyMatrix[1].points[0].x_cord; (this is just an example)
Sample code that produces problem:
STRUCTS:
struct matrice {
char M_name[256];
int num_points[128];
int set_points[128];
int hasValues[1];
struct matrice_points * points;
} * MyMatrix;
struct matrice_points {
int set[1];
double cord_x;
double cord_y;
};
Setup Matrix Function:
void setupMatrix(){
MyMatrix = calloc(1, sizeof(*MyMatrix));
numMatrix = 1;
}
Grow Matrix Function:
void growMatrix(){
MyMatrix = realloc(MyMatrix, numMatrix * 2 * sizeof(*MyMatrix));
numMatrix = numMatrix * 2;
}
Add Matrix Function which outputs this problem after growing the matrix once.
void addMatrix(char Name, int Location){
int exists = 0;
int existsLocation = 0;
for (int i = 0; i < numMatrix; i++){
if (strcmp(MyMatrix[i].M_name, &Name) == 0){
exists = 1;
existsLocation = i;
}
}
*MyMatrix[Location].M_name = Name;
printf("Stored Name: %s\n", MyMatrix[Location].M_name);
*MyMatrix[Location].num_points = 1;
*MyMatrix[Location].set_points = 0;
*MyMatrix[Location].hasValues = 1;
MyMatrix[Location].points = calloc(1, sizeof(*MyMatrix[Location].points));
}
void addMatrix(char Name, int Location)
char Name represents a single char, i.e. a integer-type quantity. char is just a number, it's not a string at all.
When you do this:
strcmp(..., &Name)
you're assuming that the location where that one character is stored represents a valid C string. This is wrong, there is no reason why this should be the case. If you want to pass a C string to this function, you will need to declare it like this:
void addMatrix(char *Name, int Location)
Then you need to copy that C string into the appropriate place in your matrix structure. It should look like:
strncpy(... .M_name, Name, max_number_of_chars_you_can_store_in_M_Name);
Also these field definitions are strange in your struct:
int num_points[128];
int set_points[128];
int hasValues[1];
This means that your struct will contain an array of 128 ints called num_points, another array of 128 ints calls set_points, and an array of one int (strange) called hasValues. If you only need to store the count of total points and set points, and a flag indicating whether values are stored, the definition should be:
int num_points;
int set_points;
int hasValues;
and correct the assignments in your addMatrix function.
If you do need those arrays, then your assignments as they are are wrong also.
Please turn on all warnings in your compiler.
Try adding '\0' to the end of your data.
*MyMatrix[Location].M_name = Name;
You're copying a single character here, not a string. If you want a string, Name should be defined as char *, and you should be using strcpy.

Resources