Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : csub and array - help please
Page 1 of 2 | |||||
Author | Message | ||||
homa Guru Joined: 05/11/2021 Location: GermanyPosts: 351 |
Can someone explain to me with a simple example how I pass an array from mmbasic to a csub? increase the values in it by one and get another one back if necessary? dim t% = (1,2,3,4) dim t2%(3) ctest t%(),t2%() csub ctest ... end csub What does the C part look like for compiling ... ? #include <stddef.h> void ctest(long long int *t[], long long int *t2[]) { ??? call ok? ?? and here how? } |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 4038 |
I'm guessing, because it's been a while since I looked at CSUBs and I can't recall whether I did arrays: #include <stdint.h> void ctest(int64_t len, int64_t* t1, int64_t* t2) { for (int i = 0; i < len; ++i) { t2[i] = t1[i] + 1; } } And call with: ctest 4, t%(), t2%() Note how you need to pass in the length of the array, C doesn't know how long a normal array passed as an argument is. Good luck, Tom Edited 2024-03-07 05:54 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
homa Guru Joined: 05/11/2021 Location: GermanyPosts: 351 |
Error: Invalid address - resetting No luck :-( Matthias Edited 2024-03-07 06:44 by homa |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 4038 |
Try this: #include <stdint.h> void ctest(int64_t* len, int64_t t1[], int64_t t2[]) { for (int i = 0; i < *len; ++i) { ' <-- Note *len t2[i] = t1[i] + 1; } } Best wishes, Tom Edited 2024-03-07 06:58 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
homa Guru Joined: 05/11/2021 Location: GermanyPosts: 351 |
does! thx but what exactly is the * for ? i'm still at the very beginning with c #include <stdint.h> void ctest(int64_t* len, int64_t t1[], int64_t t2[]) { ' <-- and why here and not *len ? for (int i = 0; i < *len; ++i) { ' <-- Note *len t2[i] = t1[i] + 1; } } and why doesn't this work (yes, the variable names don't fit, but just as an example)? size_t n = sizeof(a) / sizeof(a[0]); Matthias Edited 2024-03-07 07:27 by homa |
||||
LeoNicolas Guru Joined: 07/10/2020 Location: CanadaPosts: 479 |
The * means you are passing a pointer to a memory region, instead of a value. For arrays your are passing the start address in memory of the array. |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1241 |
and applied to a pointer this means a dereference. I.e. the contents of the memory at the location referenced by the pointer. But Matthias does it very well! Congratulations! Michael I put together the above code again. Dim t%(3) = (1,2,3,4) Dim t2%(3),l%,i% l% = Bound(t2%()) ctest l%, t%(), t2%() For i%=0 To l% Print i%,t%(i%),t2%(i%) Next End 'File arrayinc1.bas written 06-03-2024 23:15:29 v1.44 CSub ctest 00000000 B087B5F0 60F8AF00 607A60B9 617B2300 697BE012 68BA00DB 681A18D3 6979685B 687800C9 20011846 18122100 6032414B 697B6073 617B3301 001C697B 001D17DB 681A68FB 429D685B D1E2DC02 D9E04294 46BD46C0 BDF0B007 End CSub #include <stdint.h> #include "PicoCFunctions.h" void ctest(int64_t* len, int64_t t1[], int64_t t2[]) { for (int i = 0; i <= *len; ++i) { t2[i] = t1[i]+1; } } causality ≠ correlation ≠ coincidence |
||||
JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 3801 |
Then when you use the pointer (i < *len) it means to use the value it (*len) points to. John |
||||
vegipete Guru Joined: 29/01/2013 Location: CanadaPosts: 1109 |
MATH ADD in(), 1 ,out() Of course, that won't learn ya nuttin about CSUBs. Visit Vegipete's *Mite Library for cool programs. |
||||
homa Guru Joined: 05/11/2021 Location: GermanyPosts: 351 |
Thank you all, Michael: bound in basic is a good solution. Thanks for explaining the * as a pointer to the address. But my question why the * in the function name is "int64_t* len" on the left and then "*len" is still not answered. And why does the array not need a *=pointer? Is that per se always the start address through the square brackets []? Why a sizeof does not work is also only partly self-explanatory. In C itself, the program also knows when a function is called with an array, doesn't it? Phew, C is different. Matthias |
||||
Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 6786 |
C is closely related to an antiquarian minor dialect of Njerep, I think. It may as well be to me. :) Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 4038 |
In this function prototype: void ctest(int64_t* len, int64_t t1[], int64_t t2[]); int64_t* len Says that `len` is a pointer to (i.e. the address of) an int64_t containing the length. Within the function: - The value of `len` is the memory address. - The value of `*len` is the contents of that memory address, you are de-referencing the pointer. Note that MMBasic doesn't simply pass the value of `len` because MMBasic passes arguments to ALL (not just CSUB) subroutines and functions by reference not by value. This function prototype: void ctest(int64_t* len, int64_t* t1, int64_t* t2); Means exactly the same thing to the compiler as the first one, and is infact the canonical form with the former just being prettier. When you pass an array to a function you always pass a pointer to the first (0'th) element of that array. MMBasic does not pass the address of the array, it passes the address of the first element of the array which is why you don't need ** or a * and a []. Why a sizeof does not work is also only partly self-explanatory. In C itself, the program also knows when a function is called with an array, doesn't it? sizeof() is evaluated at compile time (excluding C99 variable length arrays which are out of scope) and thus can't be used to determine the size of an array passed to a function. sizeof(t), sizeof(t1), sizeof(t2) will all be identical = 4 because they are 32-bit pointers. Note however with a local or global variable (not parameter) in a function you can do: void foo() { int64_t a[10]; printf("%d\n", sizeof(a) / sizeof(a[0])); } And this (assuming I haven't cocked up) will print 10 because the sizeof(a) is 80 bytes and the size of one element is 8 bytes. So is Spanish ;-) Best wishes, Tom Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1241 |
Very well explained, Tom! ähmm ... not 64-bit pointers? Best regards Michael causality ≠ correlation ≠ coincidence |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9115 |
Matthias You are asking questions about basic C syntax so the full answer is Kernighan and Ritchie "The C programming language" which is available online free if you look. C is very easy and maps pretty much 1:1 onto MMBasic EXCEPT for pointers and pointers are what makes C so powerful I'll try and answer your questions but you will find you need to go deeper than we can answer in a forum thread. sizeof can only work on declared data so int b[10]; int c=sizeof(b); works but MMbasic does not declare arrays in that way. It creates them on a pre-allocated area of memory called the MMBasic Heap. Therefore sizeof cannot know their size When you enter a CSub passing a Basic variable "BVar" then the CSub gets a pointer to the memory holding that variable; let's call that pointer Cvar *Cvar says "the data item that is pointed to by Cvar" So in Tom's code *len is the actual value passed by MMBasic whereas just "len" is the pointer to that data item. Now lets look at arrays. When you pass an array to a CSub what the CSub sees is a pointer to the first element of the array so: *Cvar is exactly the same as Cvar[0] in both cases a pointer to the first element of the array. How then do we get the second element of the array? Cvar[1] obviously. But what this is doing is effectively adding the size of a single element (8 bytes in our case) to Cvar and using this new pointer to get the data |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 4038 |
Thanks. I don't get your point, `len`, `t1` and `t2` are I believe, at least on the Pico, 32-bit pointers to 64-bit integers. Without running it myself, the output from: printf("%d,%d\n", sizeof(len), sizeof(*len)); printf("%d,%d\n", sizeof(t1), sizeof(*t1)); printf("%d,%d\n", sizeof(t2), sizeof(*t1)); Should be: 4,8 4,8 4,8 Best wishes, Tom Edited 2024-03-07 23:19 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1241 |
Tom: sorry, my mistake! I was confused. Michael causality ≠ correlation ≠ coincidence |
||||
homa Guru Joined: 05/11/2021 Location: GermanyPosts: 351 |
Hi Tom and Peter, Thanks a lot for helping me out here! Dude, I still have this on my shelf and in German, but it's still Spanish to me, I have a bad translation ;-) No kidding, a later edition must be much better in translation. I'll see if I can still find it. Reading English is okay, but really learning it is a challenge for me as an old man. @Tom I was confused about the *-pointer because I read it here, directly to the right of the variable name and not to the left of the type: https://www.thebackshed.com/forum/ViewTopic.php?TID=12289&PID=149258#149258 void waitabit(long long int *w){ uSec(*w); } Thanks again and I will now try it with the Raycaster, the weekend can come ... Matthias |
||||
JohnS Guru Joined: 18/11/2011 Location: United KingdomPosts: 3801 |
void waitabit(long long int *w){ uSec(*w); } That looks like you have left & right swapped. When starting out, it's probably best to stick to as few pointers as you can, and especially to as few levels of indirection (it's possible to have pointers to pointers etc, which can confuse). C's quite a compact yet powerful language. MMBasic is quite a big, complex thing and it uses lots of C's features. Some of the C syntax takes some getting used to. In other words, for a C beginner trying to get used to MMBasic's internals, you have quite a cliff to climb. John |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 4038 |
void waitabit(long long int *w){ uSec(*w); } OK, so the whitespace around the * is I'm pretty sure always irrelevant, for a pointer I usually put it with the type so I would have written: void waitabit(long long int* w){ uSec(*w); } Except I wouldn't have written `long long int` because at least when I learnt C that could be anything for 32-128 bits long. In this case I would use int64_t which is guaranteed (?) to be a 64 bit integer, so: void waitabit(int64_t* w){ uSec(*w); } And in this case `w` is a 32-bit pointer to the time you want to "wait" and `*w` is the 64-bit time you want to wait. Best wishes, Tom Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9115 |
I'm never sure on this one so I always put it with the variable int64_t* a,b; int64_t *a,b; |
||||
Page 1 of 2 |
Print this page |