The following function, populateArpeggioArray, takes a pointer to a typedef'd struct containing several members, the identities of which are not necessarily relevant to the issue that I have. populateArpeggioArray should perform a few operations on the internal elements of the structure before passing a pointer to the struct to the function sortNoteStack.
What I've found is that the struct is never operated upon by sortNoteStack, because populateArpeggioArray, at some point, changes the value of the pointer to the struct before passing the changed value to sortNoteStack.
As far as I can tell, the code seems to be formatted properly, with proper pointer dereferencing for all operations performed on the elements of the struct. From what I can see, none of the lines of code should be able to modify the value of the pointer to the struct. Declaring the struct with the const prefix does not help, as its members are therefore also locked to a fixed value.
I'm open to the idea that this may be a problem with the simulator, and not the code, but if there is some latent issue with the code I have written, I'd certainly like to understand what I'm doing incorrectly.
Thank you for your help.
-Nick
void populateArpeggioArray(arpeggio* arp) {
uint8_t i = 0,j=0, newNoteFlag=0;
for(i=0; i<12; i++) {
newNoteFlag = 0;
if(globals.keyboardCurrentState[i]) { /* Check to see if the current state shows that a keyboard button is pressed. */
arp->sequenceLength++; /* Temporarily increase the sequence length */
for(j=0;j < arp->sequenceLength;j++) { /* Check the pitch of each note currently in the note stack */
if(globals.keyboardNotes[i] == arp->notesUnordered[j].pitch) { /* If the currently selected note is already present in the note stack, */
arp->sequenceLength--;
newNoteFlag = 1; /* undo the temporary sequence length increase */
}
}
if(!newNoteFlag) {
arp->notesOrdered[arp->sequenceLength].pitch = globals.keyboardNotes[i]+liveArpeggio.transposeShift;
arp->notesUnordered[arp->sequenceLength].pitch = globals.keyboardNotes[i]+liveArpeggio.transposeShift; /* Add the new pitch to the appended note */
arp->notesOrdered[arp->sequenceLength].length = 111;
arp->notesUnordered[arp->sequenceLength].length = 111; /* Give the new note a default length. TEMP */
}
}
}
sortNoteStack(&arp);
}
With sortNoteStack(&arp), you're passing the address of the pointer, not the address of the struct. You want to pass the address of the struct (the value of the pointer). Thus, use sortNoteStack(arp).
Related
I'm new to C programming and having a hard time differentiating this syntax
ptr = &array[index]
against this one
*ptr = array[index]
In a sample function I worth
void getDevice(Device* device)
the line works just like I expect it to
*device = devices[index];
(de-referenced device pointer now has value devices[index])
but this line causes segfault
device = &devices[index];
(device pointer has devices[index]'s address)
I think both ultimately should have same effect (ptr pointing to devices[index]). What am I missing here?
Actual code:
void populatePhysicalDevice(VkInstance* gInstance, VkPhysicalDevice* gPhysicalDevice)
{
uint32_t physicalDeviceCount = 0;
vkEnumeratePhysicalDevices(*gInstance, &physicalDeviceCount, VK_NULL_HANDLE);
VkPhysicalDevice physicalDevices[physicalDeviceCount];
vkEnumeratePhysicalDevices(*gInstance, &physicalDeviceCount, physicalDevices);
int bestSuitedPhysicalDeviceLocation = 0;
gPhysicalDevice = &physicalDevices[bestSuitedPhysicalDeviceLocation]; // Causes segfault
*gPhysicalDevice = physicalDevices[bestSuitedPhysicalDeviceLocation]; // Works
}
VkInstance
VkPhysicalDevice
vkEnumeratePhysicalDevices
Assuming you call your function like so:
vkInstance instance;
vkPhysicalDevice physicalDevice;
vkCreateInstance(..., &instance);
populatePhysicalDevice(&instance, &physicalDevice);
So the two values of the two arguments passed are the pointers to instance and physicalDevice in the caller's scope. The pointers (not the values they point to) get copied into the corresponding variables in populatePhysicalDevice:
void populatePhysicalDevice(VkInstance* gInstance, VkPhysicalDevice* gPhysicalDevice)
{
So at this point, inside populatePhysicalDevice(), you have two pointers that you can change at will, but will not change anything in the caller's scope. Let's go on:
uint32_t physicalDeviceCount = 0;
vkEnumeratePhysicalDevices(*gInstance, &physicalDeviceCount, VK_NULL_HANDLE);
VkPhysicalDevice physicalDevices[physicalDeviceCount];
vkEnumeratePhysicalDevices(*gInstance, &physicalDeviceCount, physicalDevices);
Now you have a local array of VKPhysicalDevices, that has been filled in by vkEnumeratePhysicalDevices(). Now you want to ensure that the caller gets a copy of the best suited physical device:
int bestSuitedPhysicalDeviceLocation = 0;
gPhysicalDevice = &physicalDevices[bestSuitedPhysicalDeviceLocation]; // Causes segfault
That line doesn't do anything that the caller will see. It will just change the local variabel gPhysicalDevice to point to the start of the local array physicalDevices. When you return, all those things go away. The end result is that [hysicalDevice in the caller's scope has not been initialized. That is the likely cause of the segmentation fault.
When you do this instead:
*gPhysicalDevice = physicalDevices[bestSuitedPhysicalDeviceLocation]; // Works
You are actually copying the value of the first element of physicalDevices[] into the variable physicalDevice in the caller's scope.
Note that if you are just always going for the first physical device, you do not need to create a local array, you could instead just do:
void populatePhysicalDevice(VkInstance* gInstance, VkPhysicalDevice* gPhysicalDevice)
{
vkEnumeratePhysicalDevices(*gInstance, 1, gPhysicalDevices);
}
But don't forget that the instance might not actually have any physical devices available, so check the return values of the functions you call and make sure they are as expected!
ptr = &array[index] sets ptr to point to array[index]. That is, it puts the address of array[index] into ptr.
*ptr = array[index] sets *ptr to the value array[index]. That is, it gets the value stored in array[index] and put that value in the place pointed to by ptr. It does not change ptr.
The cause of the segment fault you report cannot be ascertained because you have not provided sufficient code or information. The line device = &devices[index]; by itself is likely not the cause.
I am having a problem correctly dereferencing a pointer to an integer that resides in an array of structures. The relevant parts of the code are:
typedef struct hf_register_info {
int *p_id; /**< written to by register() function */
header_field_info hfinfo; /**< the field info to be registered */
} hf_register_info;
.
.
hf_register_info hf[MAX_HF_COUNT];
.
.
*(hf[i].p_id) = -1;
The final line of code above causes an exception. How do I correctly deference p_id?
Thanks and regards...Paul
You need to initialize your pointers. You pointers in your structs aren't pointing to anything at the moment you initialize your array.
So for every struct in your array you want to dereference your pointer and assign a value to, you'll need to allocate space in your memory first.
hf_register_info hf[MAX_HF_COUNT];
// some code here
hf[i].p_id = malloc(sizeof(int)); // or unsigned long or whatever
*(hf[i].p_id) = -1;
It was, actually, the display function after all. Sorry if I wasted your time (I didn't actually put the code of the display function here, my bad. However, I did learn some new things, so thank you all!
I have created a structure which involves an array that represents a set of integers.
When I first create a structure, I use malloc() to allocate space for the structure and thus, the array.
The problem resides, however, in the fact that when I create the structure, the first element of the array is being assigned a number. I want, however, to just create a structure where the array in it is uninitialised.
typedef struct set{
int numberOfValues; /* The number of values in the set */
int value[40]; /* the set */
} *Set; /* Set is thus a pointer to struct set */
Set aOfPStructs[4];
void create()
{
static int setnum = 0;
Set S; /* S is a pointer to struct set */
if (setnum <= 4)
{
S = (struct set *) malloc(sizeof(struct set));
S->numberOfValues = 0;
aOfPStructs[setnum] = S;
printf("The set's number is %d\n", setnum);
setnum++;
}
else
printf("Error. No more sets can be created.\n");
}
The above is only a snippet from the whole program, but any other code is irrelevant to the question tbh.
So with that code, if I were to display the contents of the array in the structure, I would get 1 value. Thing is, I have not added any elements to the array, so I should get no values at this point. Can I fix this?
Any help would be appreciated! Thanks!
Edit:
I tried memset(), but it's not exactly what I want. When I use the create(), I want 0 elements in the array value[], but the code is generating 1 random element once I use the create function.
The function. to display the element seems to work just fine though. Funny thing is, when I run a function to delete one element from the array, that extra element is removed, only to be added again if I run the add() function.
Edit 2:
Added a screenshot for further explanation of my problem. I appreciate every comment thus far, and future ones too.
http://imgur.com/cza3ip6
Edit 3:
Ok, I get the use of memset() now and the concept of initialisation. Thing is, if I wanted to check the number of elements of the set, just right after I create it, I should get 0 because I have not added any elements, but an element is being generated with create...
I think you may not understand what "initialized" and "uninitialized" mean.
"Uninitialized" means "holding whatever bit pattern happens to be left over from the last computation that used this memory or from bootstrapping the machine."
"Initialized" just means you have assigned a set value.
The malloc call gives you uninitialized storage according to this definition. So what you are seeing is the best you can get. You are printing the integer formed from the arbitrary bit pattern in the first array slot.
For what it's worth, the simplest way to get a pre-zeroed memory block of n ints (initialized to zero) is to say.
int *blk = calloc(n, sizeof(int));
Use memset to set to 0 all the data in the structure. By default when you use malloc the memory you get is not initiliazed:
S = (struct set *) malloc(sizeof(struct set));
memset(S, 0, sizeof(struct set));
Try this. It uses a little different approach to create and initialize array of structs, but the relevant point is that it uses memset to init array of ints for each element of struct array:
#include<stdio.h>
typedef struct {
int numberOfValues; /* The number of values in the set */
int value[40]; /* the set */
}SET;
SET set[4], *pSet; //initialize SET *, pSet to the first position of set
main()
{
int i;
pSet= &set[0];
for(i=0;i<4;i++)
{
memset(pSet[i].value, 0, sizeof(int)*40); //set all elements of member value to 0
}
}
You haven't posted the function displaying your set. I suppose that the problem may be there. Maybe you use something like for(i=0; i <= S->numberOfValues; i++) instead of for(i=0; i < S->numberOfValues; i++), so you print the first element even if not there.
**Issue overview **
The current issue i have is that i have an array which has the size of a variable which happens to be the amount of lines in a file. This is an integer which is calculated and returned, which becomes the arraysize (e.g. file text.txt has 12 lines so the array is of size 12).
I want to know how i can return this value to another c file for use in a function so i can loop through the complete array.
points to note
I am not allowed any globals at all in this assignment, no global arrays/variables at all.
The line counting functions works correctly so i will not be posting it here
The array is set up correctly and print the correct results
Most of the code from the functions has been removed to make it easier to read.
The correct #includes for each file are present, i just need an example of how to do it.
The code:
void read_from_file() {
/* reading and parsing removed */
no_of_lines = (count_lines(locof) - 1);
/* locof is a char array storing the file name */
ship ships[no_of_lines];
/* i want to return the value of no_of_lines *?
I want to return the value of no_of_lines
The c file where i need the value
/*This is where i need the variable */
void asign_mayday_to_ships() {
int* ship_arr_length = SIZE OF SHIP ARRAY NEEDED
mayday_call* mday_ptr;
ship* ship_ptr; /* this is a ship array */
mday_ptr = read_mayday_file();
ship_ptr = read_ship_locations();
int i;
for(i = 0; i < SIZE OF SHIP ARRAY; i++){
}
Just pass both pointer and size, it'a a C way.
void read_from_file() {
/* reading and parsing removed */
no_of_lines = (count_lines(locof) - 1);
/* locof is a char array storing the file name */
ship ships[no_of_lines];
some_fun_from_second_file(ships, no_of_lines);
Who calls the two fnctions? Can't you just return the nr of lines in an upper function then pass it in the second one? If not, then you must somehow store it in a variable(or a struct member) and then you can grab it later. This is a contextual solution, it might not work for you.
i had to first malloc my ships array, then set the size of the malloc depending on the amount of elements then i can return the size of the pointer:
ship* ships;
ships = malloc(sizeof (ship) * no_of_lines);
the in the function i was having trouble with:
mayday_call* mday_ptr;
ship* ship_ptr;
mday_ptr = read_mayday_file();
ship_ptr = read_ship_locations();
int arr_size = sizeof (ship_ptr) ;
int i;
for(i =0; i < arr_size; i++) {
//do something
}
`
sounds like your 'teacher' wants make you use a sentinel value. Ie put an object at the end of the array that cannot exist (a ship with name all spaces for example) then in the array processing you keep looping till you hit the magic value.
This is a bad design, but if you aren't allow globals and you aren't allow parameters I cant see what else to do
i have a simple structure:
typedef struct {
int test;
} struct1_t;
typedef struct {
struct1_t** tests;
} struct2_t;
struct2_t *str
for(i=0;i<1000;i++) {
(str->tests)[i]=(test1_t *) malloc(sizeof(test1_t));
(str->tests)[i]->test = i;
}
How to know exist str->tests)[i] element on not ?
if (str->tests)[i] != NULL
call Segmentation failed :).
Simply put, you can't. There is no way to know the length of an array in C, you have to keep track of it manually as your array changes or grows.
C arrays are really just blocks of memory, so what you really
want to do as add a field to your structs that keeps track of how
much space has been allocated and make sure you initialize
everything to sane values. You also have to be careful when using
pointers of structs containing to pointers to pointers of structs,
since in your example you failed to properly allocate memory for
everything.
Try this:
typedef struct {
int test;
} test_t;
typedef struct {
test_t* tests; /* We only need a regular pointer here */
size_t numtests; /* This is so we know how many tests we allocated */
} mystruct_t;
/* .... Now skip to the actual usage: */
mystruct_t *str;
int i;
str = malloc(sizeof(mystruct_t)); /* Remember to allocate memory for
the container! */
str->numtests = 1000; /* Set our size inside the container and use it! */
/* Now to allocate an array of tests, we only need to allocate
a single chunk of memory whose size is the number of tests
multiplied by the size of each test: */
str->tests = malloc(sizeof(test_t)*str->numtests);
/* Now let's initialize each test: */
for (i=0; i<str->numtests; i++) { /* Notice we use str->numtests again! */
str->tests[i]->test = 1; /* Notice we don't need all the extra
parenthesese. This is due to the operator
precedence of [] and -> */
}
Now when you need to see if a test element exists, you can just see if the
index is within the size of the container:
if (i >= 0 && i < str->numtests) {
str->tests[i]->test = 2; /* This code only runs if the index would exist. */
}
But that means you have to take care to always initialize str->numtests to be
a sane value. For example, with no allocated tests:
mystruct_t *str = malloc(sizeof(mystruct_t));
/* Initialize the container to sane starting values! */
str->tests = NULL;
str->numtests = 0;
And that's how you know if something exists -- you keep track of it inside
the structures you define. That's because C code maps very directly to
assembly language, and C structs and arrays map very directly to bits and bytes
in computer memory, so if you want to maintain meta information like how
many elements are inside your array, you have to make room for that information
and store it yourself.
It is pretty fundamental that you can't do it this way in C. Your struct2_t would need an extra field such as int no_of_tests, which you would update.
In fact to do what your trying to do there, you also need 2 mallocs -
struct2_t str;
str.tests = malloc( 1000 * sizeof(int) );
str.no_of_tests = 1000;
for(i=0;i<1000;i++) {
str.tests[i] = malloc( sizeof(struct1_t) );
str.tests[1]->test = i;
}
There is nothing in the language to do this for you, you need to keep track yourself. A common solution is to make the last pointer in an arbitrary-size array of pointers be a NULL pointer, so you know to stop looping when you hit NULL.
If your compiler supports _msize you can find out the size that you allocated. For example:
if (i < _msize((str->tests)/sizeof(test1_t))
then i is valid and points to an element of the allocated array