指针到C指针的麻烦

时间:2019-01-24 06:43:14

标签: c pointers

我试图用C语言编写某种列表,而没有为列表的开头创建全局变量,这给我带来了麻烦。

我原来的代码是这样的:

struct AnchoredConstraints {
    var top, leading, bottom, trailing, width, height: NSLayoutConstraint?
}

extension UIView {
    @discardableResult
    func anchor(top: NSLayoutYAxisAnchor? = nil, leading: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, trailing: NSLayoutXAxisAnchor? = nil, padding: UIEdgeInsets = .zero, size: CGSize = .zero) -> AnchoredConstraints {
        translatesAutoresizingMaskIntoConstraints = false
        var anchoredConstraints = AnchoredConstraints()

        if let top = top {
            anchoredConstraints.top = topAnchor.constraint(equalTo: top, constant: padding.top)
        }

        if let leading = leading {
            anchoredConstraints.leading = leadingAnchor.constraint(equalTo: leading, constant: padding.left)
        }

        if let bottom = bottom {
            anchoredConstraints.bottom = bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom)
        }

        if let trailing = trailing {
            anchoredConstraints.trailing = trailingAnchor.constraint(equalTo: trailing, constant: -padding.right)
        }

        if size.width != 0 {
            anchoredConstraints.width = widthAnchor.constraint(equalToConstant: size.width)
        }

        if size.height != 0 {
            anchoredConstraints.height = heightAnchor.constraint(equalToConstant: size.height)
        }

        [anchoredConstraints.top, anchoredConstraints.leading, anchoredConstraints.bottom, anchoredConstraints.trailing, anchoredConstraints.width, anchoredConstraints.height].forEach { $0?.isActive = true }

        return anchoredConstraints
    }

    func anchor(
        top: NSLayoutYAxisAnchor? = nil, left: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, right: NSLayoutXAxisAnchor? = nil,
        paddingTop: CGFloat = 0, paddingLeft: CGFloat = 0, paddingBottom: CGFloat = 0, paddingRight: CGFloat = 0,
        width: CGFloat = 0, height: CGFloat = 0,
        centerX: NSLayoutXAxisAnchor? = nil, centerY: NSLayoutYAxisAnchor? = nil
        ) {
        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            self.topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
        }

        if let left = left {
            self.leadingAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
        }

        if let bottom = bottom {
            self.bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true
        }

        if let right = right {
            self.trailingAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true
        }

        if width != 0 {
            widthAnchor.constraint(equalToConstant: width).isActive = true
        }

        if height != 0 {
            heightAnchor.constraint(equalToConstant: height).isActive = true
        }

        if let centerX = centerX {
            self.centerXAnchor.constraint(equalTo: centerX).isActive = true
        }

        if let centerY = centerY {
            self.centerYAnchor.constraint(equalTo: centerY).isActive = true
        }
    }


    func fillSuperview(padding: UIEdgeInsets = .zero) {
        translatesAutoresizingMaskIntoConstraints = false
        if let superviewTopAnchor = superview?.topAnchor {
            topAnchor.constraint(equalTo: superviewTopAnchor, constant: padding.top).isActive = true
        }

        if let superviewBottomAnchor = superview?.bottomAnchor {
            bottomAnchor.constraint(equalTo: superviewBottomAnchor, constant: -padding.bottom).isActive = true
        }

        if let superviewLeadingAnchor = superview?.leadingAnchor {
            leadingAnchor.constraint(equalTo: superviewLeadingAnchor, constant: padding.left).isActive = true
        }

        if let superviewTrailingAnchor = superview?.trailingAnchor {
            trailingAnchor.constraint(equalTo: superviewTrailingAnchor, constant: -padding.right).isActive = true
        }
    }

    func centerInSuperview(size: CGSize = .zero) {
        translatesAutoresizingMaskIntoConstraints = false
        if let superviewCenterXAnchor = superview?.centerXAnchor {
            centerXAnchor.constraint(equalTo: superviewCenterXAnchor).isActive = true
        }

        if let superviewCenterYAnchor = superview?.centerYAnchor {
            centerYAnchor.constraint(equalTo: superviewCenterYAnchor).isActive = true
        }

        if size.width != 0 {
            widthAnchor.constraint(equalToConstant: size.width).isActive = true
        }

        if size.height != 0 {
            heightAnchor.constraint(equalToConstant: size.height).isActive = true
        }
    }
}



生成输出:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

struct Node {
    char *data;
    struct Node *next;
};

struct Node *init(struct Node *head) {
    head = malloc(sizeof(struct Node));
    head->data = "abc";
    head->next = NULL;

    return head;
}

struct Node *getHead(struct Node *head) {
    struct Node *retNode = NULL;

    if (head != NULL) {
        retNode = head;
        head = head->next;
    }

    return retNode;
}

int main(int argc, char **argv) {
    struct Node *head;
    head = init(head);
    printf("Head pointer before method:%p\n", head);

    getHead(head);
    printf("Head pointer after method:%p\n", head);
}

我以为这是失败的,因为C是通过值传递的,这使我认为方法内部显示了具有不同指针的相同副本。但是,当我检查方法中指向Head的指针时,我发现它与原始的head指针相同,因此看起来实际的指针在方法中。我不明白这里发生了什么,所以如果有人可以解释为什么即使存在相同的指针也不会更新头部指针的原因。

我认为它应该工作,因为如果您有一个swap(int * a,int * b)方法并且实际的指针是从main发送的,则内部进行的更改将同时影响外部的变量。在网上看了之后,人们说要为此使用指针,尽管我似乎无法使其正常工作。

尝试对其进行如下编码:

Head pointer before method:0x7fffd36ad260  
Head pointer after method:0x7fffd36ad260

尽管在尝试编译时会遇到错误:

//... same code as before for other methods
struct Node *getHead(struct Node **head)
{
    struct Node *retNode = NULL;

    if (head != NULL)
    {
        retNode = *head;
        *head = *head->next;
    }

    return retNode;
}

int main(int argc, char **argv)
{
    struct Node *head;
    head = init(head);
    printf("Head pointer before method:%p\n", head);

    getHead(&head);
    printf("Head pointer after method:%p\n", head);
} 

我也不知道为什么会引发此错误。

2 个答案:

答案 0 :(得分:0)

就像其他人已经指出的那样,由于运算符的优越性,您必须将*head放在括号中。

我有一个理解上的问题,为什么您要用其后继覆盖head?函数getHead应该更好地称为removeHead吗?

还请注意,您的函数head中的init参数无效,因为它被以下malloc覆盖。

我还建议阅读有关Linux内核如何实现有效的lists using struct embedding的精彩文章。很高兴!

答案 1 :(得分:-2)

将双指针传递到getHead,因为您试图在调用head的作用域中更新getHead

struct Node *getHead(struct Node **head) {
    struct Node *retNode = NULL;

    if (head != NULL && *head != NULL) {
        retNode = *head;
        *head = (*head)->next;
    }

    return retNode;
}

在第一次尝试之前和之后,head的值相同是因为您从未更改headmain的值。您的函数getHead更改其指针head的本地副本。因此,如果您第一次尝试在head内打印getHead,则会看到它指向另一个地址。